sat-multicast-example.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Magister Solutions
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Frans Laakso <frans.laakso@magister.fi>
19  *
20  */
21 
22 #include "ns3/applications-module.h"
23 #include "ns3/core-module.h"
24 #include "ns3/internet-module.h"
25 #include "ns3/network-module.h"
26 #include "ns3/satellite-module.h"
27 #include "ns3/traffic-module.h"
28 
29 using namespace ns3;
30 
43 NS_LOG_COMPONENT_DEFINE("sat-multicast-example");
44 
50 static void
51 SinkReceive(std::string context, Ptr<const Packet>, const Address&)
52 {
53  NS_LOG_INFO(" Packet received from/by: " << context);
54 }
55 
63 static std::string
64 GetUserInfo(Ptr<SatHelper> helper, Ptr<Node> node)
65 {
66  std::stringstream ss; // create a string stream
67  Ptr<Node> utNode = Singleton<SatTopology>::Get()->GetUtNode(node);
68  NodeContainer nodeUsers;
69 
70  if (utNode)
71  {
72  nodeUsers = Singleton<SatTopology>::Get()->GetUtUserNodes(utNode);
73  ss << "UT"
74  << Singleton<SatIdMapper>::Get()->GetUtIdWithMac(
75  Singleton<SatIdMapper>::Get()->GetUtMacWithNode(utNode))
76  << "-user-";
77  }
78  else
79  {
80  nodeUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
81  ss << "GW-user-";
82  }
83 
84  uint32_t userIndex = 0;
85 
86  for (uint32_t j = 0; ((j < nodeUsers.GetN()) && (userIndex == 0)); j++)
87  {
88  if (nodeUsers.Get(j) == node)
89  {
90  userIndex = j + 1;
91  }
92  }
93 
94  ss << userIndex;
95 
96  return ss.str();
97 }
98 
102 static void
104 {
105  NS_LOG_INFO("");
106 }
107 
120 static Time
121 EstablishMulticastGroup(Ptr<SatHelper> helper,
122  Ptr<Node> source,
123  NodeContainer groupReceivers,
124  Ipv4Address groupAddress,
125  uint16_t port,
126  Time startTime,
127  bool sinkToAll)
128 {
129  Time time = startTime;
130 
131  NS_LOG_INFO("--- Create multicast group " << groupAddress << " ---");
132 
133  helper->SetMulticastGroupRoutes(source,
134  groupReceivers,
135  helper->GetUserAddress(source),
136  groupAddress);
137 
138  NS_LOG_INFO("--- Creating traffic generator for " << groupAddress << " ---");
139 
140  // CBR traffic generator for multicast group with interval 0.4s and packet size 512 bytes
141  CbrHelper cbrHelper("ns3::UdpSocketFactory", InetSocketAddress(groupAddress, port));
142  cbrHelper.SetAttribute("Interval", StringValue("0.4s"));
143  cbrHelper.SetAttribute("PacketSize", UintegerValue(512));
144 
145  ApplicationContainer cbr = cbrHelper.Install(source);
146  cbr.Start(startTime + Seconds(0.4));
147  cbr.Stop(startTime + Seconds(1.0));
148 
149  NS_LOG_INFO("--- Group " << groupAddress << " source: " << GetUserInfo(helper, source)
150  << " ---");
151 
152  ApplicationContainer sink;
153 
154  std::stringstream receiverInfo;
155  receiverInfo << "--- Group " << groupAddress << " receivers: ";
156 
157  if (sinkToAll)
158  {
159  NodeContainer users = NodeContainer(Singleton<SatTopology>::Get()->GetGwUserNodes(),
160  Singleton<SatTopology>::Get()->GetUtUserNodes());
161 
162  PacketSinkHelper sinkHelperGroup("ns3::UdpSocketFactory",
163  InetSocketAddress(groupAddress, port));
164 
165  // Sinks for group receivers
166  for (uint32_t i = 0; i < users.GetN(); i++)
167  {
168  sink.Add(sinkHelperGroup.Install(users.Get(i)));
169 
170  std::string nodeName = GetUserInfo(helper, users.Get(i));
171  std::stringstream context;
172  context << groupAddress << "/" << nodeName;
173 
174  DynamicCast<PacketSink>(sink.Get(i))
175  ->TraceConnect("Rx", context.str(), MakeCallback(&SinkReceive));
176  }
177 
178  // output real group receivers
179  for (uint32_t i = 0; i < groupReceivers.GetN(); i++)
180  {
181  std::string nodeName = GetUserInfo(helper, groupReceivers.Get(i));
182  receiverInfo << nodeName << " ";
183  }
184  }
185  else
186  {
187  PacketSinkHelper sinkHelperGroup("ns3::UdpSocketFactory",
188  InetSocketAddress(groupAddress, port));
189 
190  // Sinks for group receivers
191  for (uint32_t i = 0; i < groupReceivers.GetN(); i++)
192  {
193  sink.Add(sinkHelperGroup.Install(groupReceivers.Get(i)));
194 
195  std::string nodeName = GetUserInfo(helper, groupReceivers.Get(i));
196  receiverInfo << nodeName << " ";
197 
198  std::stringstream context;
199  context << groupAddress << "/" << nodeName;
200 
201  DynamicCast<PacketSink>(sink.Get(i))
202  ->TraceConnect("Rx", context.str(), MakeCallback(&SinkReceive));
203  }
204  }
205 
206  receiverInfo << "---";
207  NS_LOG_INFO(receiverInfo.str());
208 
209  sink.Start(startTime);
210  sink.Stop(startTime + Seconds(2));
211 
212  Simulator::Schedule(startTime + Seconds(1.41), &LogEmptyLine);
213 
214  return startTime + Seconds(1);
215 }
216 
217 int
218 main(int argc, char* argv[])
219 {
221  LogComponentEnable("CbrApplication", LOG_LEVEL_INFO);
222  LogComponentEnable("PacketSink", LOG_LEVEL_INFO);
223  LogComponentEnable("sat-multicast-example", LOG_LEVEL_INFO);
224 
225  NS_LOG_INFO("--- Starting sat-multicast-example ---");
226 
227  enum PreDefinedGroup
228  {
229  ALL_GROUPS,
230  GROUP_1,
231  GROUP_2,
232  GROUP_3,
233  GROUP_4,
234  GROUP_5,
235  GROUP_6,
236  GROUP_7,
237  GROUP_8,
238  GROUP_9,
239  GROUP_10,
240  GROUP_11,
241  GROUP_12,
242  END_OF_GROUP
243  };
244 
245  uint32_t preDefinedGroup = (uint32_t)GROUP_1;
246  uint32_t fullScenarioReceivers = 10;
247  std::string scenario = "larger";
249  bool sinkToAll = false; // when set sink(s) are added to all user nodes in order to test that
250  // unnecessary routes are not added
251 
252  Ptr<Node> groupSource;
253  NodeContainer groupReceivers;
254 
256  auto simulationHelper = CreateObject<SimulationHelper>("example-multicast");
257  Config::SetDefault("ns3::SatHelper::ScenarioCreationTraceEnabled", BooleanValue(true));
258  Config::SetDefault("ns3::SatHelper::PacketTraceEnabled", BooleanValue(true));
259 
261  CommandLine cmd;
262  cmd.AddValue("scenario", "Test scenario to use. (larger or full", scenario);
263  cmd.AddValue("preDefinedGroup",
264  "Pre-defined multicast group for larger scenario. (0 = all)",
265  preDefinedGroup);
266  cmd.AddValue("fullScenarioReceivers",
267  "Number of the receivers in full scenario",
268  fullScenarioReceivers);
269  cmd.AddValue("sinkToAll", "Add multicast sink to all users.", sinkToAll);
270  simulationHelper->AddDefaultUiArguments(cmd);
271  cmd.Parse(argc, argv);
272 
274  Config::SetDefault("ns3::SatUserHelper::BackboneNetworkType",
276  Config::SetDefault("ns3::SatUserHelper::SubscriberNetworkType",
278 
279  Time startTime = Seconds(1.2);
280  simulationHelper->SetOutputTag(scenario);
281  simulationHelper->SetSimulationTime(startTime + Seconds(3.0));
282 
283  if (scenario == "larger")
284  {
285  satScenario = SatHelper::LARGER;
286  }
287  else if (scenario == "full")
288  {
289  satScenario = SatHelper::FULL;
290  }
291  else
292  {
293  NS_FATAL_ERROR(satScenario << " not supported!!!");
294  }
295 
297  // GlobalValue::Bind ("SimulatorImplementationType", StringValue
298  // ("ns3::RealtimeSimulatorImpl"));
299 
301 
302  simulationHelper->LoadScenario("geo-33E");
303 
304  // Creating the reference system.
305  Ptr<SatHelper> helper = simulationHelper->CreateSatScenario(satScenario);
306 
307  NS_LOG_INFO("--- Creating scenario: " << scenario << " ---");
308 
309  if (sinkToAll)
310  {
311  NS_LOG_INFO("--- Add sink to each users ---");
312  }
313 
314  uint16_t multicastPort = 9; // Discard port (RFC 863)
315 
317  NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtUserNodes();
318  NodeContainer gwUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
319 
320  if (scenario == "larger")
321  {
322  uint32_t currentGroup = preDefinedGroup;
323 
324  if (preDefinedGroup == ALL_GROUPS)
325  {
326  currentGroup = 1;
327  }
328 
329  for (uint32_t i = currentGroup; i < END_OF_GROUP; i++)
330  {
331  groupReceivers = NodeContainer();
332 
333  switch (i)
334  {
335  // Pre-defined group 1, Source= GW-user-1, Receivers= UT1-user-1, UT1-user-2,
336  // UT2-user-1, UT3-user-1, UT4-user-1
337  case GROUP_1:
338  groupSource = gwUsers.Get(0);
339  groupReceivers.Add(utUsers.Get(0));
340  groupReceivers.Add(utUsers.Get(1));
341  groupReceivers.Add(utUsers.Get(2));
342  groupReceivers.Add(utUsers.Get(3));
343  groupReceivers.Add(utUsers.Get(4));
344  break;
345 
346  case GROUP_2:
347  // Pre-defined group 2, Source= GW-user-1, Receivers= UT1-user-2, UT2-user-1,
348  // UT4-user-1
349  groupSource = gwUsers.Get(0);
350  groupReceivers.Add(utUsers.Get(1));
351  groupReceivers.Add(utUsers.Get(2));
352  groupReceivers.Add(utUsers.Get(4));
353  break;
354 
355  case GROUP_3:
356  // Pre-defined group 3, Source= UT1-user-1, Receivers= UT1-user-2, UT2-user-1,
357  // UT4-user-1
358  groupSource = utUsers.Get(0);
359  groupReceivers.Add(utUsers.Get(1));
360  groupReceivers.Add(utUsers.Get(2));
361  groupReceivers.Add(utUsers.Get(4));
362  break;
363 
364  case GROUP_4:
365  // Pre-defined group 4, Source= UT1-user-2, Receivers= UT2-user-1, UT4-user-1
366  groupSource = utUsers.Get(1);
367  groupReceivers.Add(utUsers.Get(2));
368  groupReceivers.Add(utUsers.Get(4));
369  break;
370 
371  case GROUP_5:
372  // Pre-defined group 5, Source= UT1-user-1, Receivers= UT3-user-1, UT4-user-1
373  groupSource = utUsers.Get(0);
374  groupReceivers.Add(utUsers.Get(3));
375  groupReceivers.Add(utUsers.Get(4));
376  break;
377 
378  case GROUP_6:
379  // Pre-defined group 6, Source= UT1-user-2, Receivers= UT2-user-1, GW-user-1
380  groupSource = utUsers.Get(1);
381  groupReceivers.Add(utUsers.Get(2));
382  groupReceivers.Add(gwUsers.Get(0));
383  break;
384 
385  case GROUP_7:
386  // Pre-defined group 7, Source= UT1-user-1, Receivers= GW-user-1
387  groupSource = utUsers.Get(0);
388  groupReceivers.Add(gwUsers.Get(0));
389  break;
390 
391  case GROUP_8:
392  // Pre-defined group 8, Source= UT1-user-2, Receivers= UT2-user-1
393  groupSource = utUsers.Get(1);
394  groupReceivers.Add(utUsers.Get(2));
395  break;
396 
397  case GROUP_9:
398  // Pre-defined group 9, Source= UT1-user-1, Receivers= GW-user-1, UT4-user-1
399  groupSource = utUsers.Get(0);
400  groupReceivers.Add(gwUsers.Get(0));
401  groupReceivers.Add(utUsers.Get(4));
402  break;
403 
404  case GROUP_10:
405  // Pre-defined group 10, Source= UT1-user-1, UT3-user-1
406  groupSource = utUsers.Get(0);
407  groupReceivers.Add(utUsers.Get(3));
408  break;
409 
410  case GROUP_11:
411  // Pre-defined group 10, Source= UT1-user-1, UT4-user-1
412  groupSource = utUsers.Get(0);
413  groupReceivers.Add(utUsers.Get(4));
414  break;
415 
416  case GROUP_12:
417  // Pre-defined group 10, Source= UT1-user-1, UT2-user-1
418  groupSource = utUsers.Get(0);
419  groupReceivers.Add(utUsers.Get(2));
420  break;
421 
422  default:
423  NS_FATAL_ERROR("Not supported pre-defined group!!!");
424  break;
425  }
426 
427  NS_LOG_INFO("--- Creating multicast pre-defined group " << preDefinedGroup << " ---");
428 
430 
431  std::stringstream groupAddress;
432  groupAddress << "225.1." << i << ".1";
433  Ipv4Address multicastGroup(groupAddress.str().c_str());
434 
435  startTime = EstablishMulticastGroup(helper,
436  groupSource,
437  groupReceivers,
438  multicastGroup,
439  multicastPort,
440  startTime,
441  sinkToAll);
442  }
443  }
444  else
445  {
446  NS_LOG_INFO("--- Creating multicast group in full scenario ---");
447 
448  // get all users
449  NodeContainer users = NodeContainer(gwUsers, utUsers);
450 
451  // add two sources from GW users and UT users randomly
452  std::vector<uint32_t> sources;
453  sources.push_back(std::rand() % gwUsers.GetN());
454  sources.push_back((std::rand() % utUsers.GetN()) + gwUsers.GetN());
455 
456  // create two multicast groups with UT and GW sources
457  for (uint32_t i = 0; i < sources.size(); i++)
458  {
459  std::vector<uint32_t> ids;
460 
461  for (uint32_t j = 0; j < users.GetN(); j++)
462  {
463  // add user only to possible receivers only if not source
464  if (j != sources[i])
465  {
466  ids.push_back(j);
467  }
468  }
469 
470  // randomize users
471  std::random_shuffle(ids.begin(), ids.end());
472 
473  // set source GW or UT users
474  groupSource = users.Get(sources[i]);
475 
476  // select reeivers
477  groupReceivers = NodeContainer();
478 
479  for (uint32_t j = 0; ((j < fullScenarioReceivers) && (j < ids.size())); j++)
480  {
481  groupReceivers.Add(users.Get(ids.at(j)));
482  }
483 
484  std::stringstream groupAddress;
485  groupAddress << "225.1." << i << ".1";
486  Ipv4Address multicastGroup(groupAddress.str().c_str());
487 
488  startTime = EstablishMulticastGroup(helper,
489  groupSource,
490  groupReceivers,
491  multicastGroup,
492  multicastPort,
493  startTime,
494  sinkToAll);
495  }
496  }
497 
498  NS_LOG_INFO("--- Running simulation ---");
499 
500  simulationHelper->RunSimulation();
501 
502  NS_LOG_INFO("--- Finished ---");
503  return 0;
504 }
PreDefinedScenario_t
Values for pre-defined scenarios to be used by helper when building satellite network topology base.
@ LARGER
LARGER Larger scenario used as base.
@ FULL
FULL Full scenario used as base.
SatArqSequenceNumber is handling the sequence numbers for the ARQ process.
static std::string GetUserInfo(Ptr< SatHelper > helper, Ptr< Node > node)
Construct information of the given user node.
static Time EstablishMulticastGroup(Ptr< SatHelper > helper, Ptr< Node > source, NodeContainer groupReceivers, Ipv4Address groupAddress, uint16_t port, Time startTime, bool sinkToAll)
Establish multicast group and generate traffic in that group.
static void SinkReceive(std::string context, Ptr< const Packet >, const Address &)
Receive RX traces from packet sinks.
static void LogEmptyLine()
Log empty line.