From d2a4d029531e1c615c4c2d251f54b3d57cf07426 Mon Sep 17 00:00:00 2001 From: Jared Dulmage Date: Tue, 12 May 2020 11:46:34 +0200 Subject: [PATCH] (internet): Example showing multicast routing setup for flooding mesh topology --- examples/routing/simple-multicast-flooding.cc | 207 ++++++++++++++++++ examples/routing/wscript | 4 + 2 files changed, 211 insertions(+) create mode 100644 examples/routing/simple-multicast-flooding.cc diff --git a/examples/routing/simple-multicast-flooding.cc b/examples/routing/simple-multicast-flooding.cc new file mode 100644 index 000000000..2411dc9bc --- /dev/null +++ b/examples/routing/simple-multicast-flooding.cc @@ -0,0 +1,207 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2013 Universita' di Firenze + * Copyright (c) 2019 Caliola Engineering, LLC : RFC 6621 multicast packet de-duplication + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Tommaso Pecorella + * Modified (2019): Jared Dulmage + * Demonstrates dissemination of multicast packets across a mesh + * network to all nodes over multiple hops. + */ + +#include "ns3/test.h" +#include "ns3/simulator.h" +#include "ns3/simple-channel.h" +#include "ns3/simple-net-device.h" +#include "ns3/socket.h" +#include "ns3/boolean.h" +#include "ns3/double.h" +#include "ns3/string.h" +#include "ns3/config.h" +#include "ns3/data-rate.h" +#include "ns3/uinteger.h" + +#include "ns3/names.h" +#include "ns3/log.h" +#include "ns3/node.h" +#include "ns3/inet-socket-address.h" +#include "ns3/random-variable-stream.h" + +#include "ns3/ipv4-l3-protocol.h" +#include "ns3/ipv4-static-routing.h" +#include "ns3/udp-socket-factory.h" +#include "ns3/udp-socket.h" +#include "ns3/packet-sink.h" + +#include "ns3/internet-stack-helper.h" +#include "ns3/ipv4-list-routing-helper.h" +#include "ns3/ipv4-static-routing-helper.h" +#include "ns3/ipv4-address-helper.h" +#include "ns3/simple-net-device-helper.h" +#include "ns3/packet-sink-helper.h" +#include "ns3/on-off-helper.h" +#include "ns3/trace-helper.h" + +#include "ns3/traffic-control-layer.h" + +#include +#include +#include + +using namespace ns3; + +/** + * Network topology: + * + * /---- B ----\ + * A ---- | ---- D ---- E + * \---- C ----/ + * + * This example demonstrates configuration of + * static routing to realize broadcast-like + * flooding of packets from node A + * across the illustrated topology. + */ +int +main (int argc, char *argv[]) +{ + // multicast target + const std::string targetAddr = "239.192.100.1"; + Config::SetDefault ("ns3::Ipv4L3Protocol::EnableDuplicatePacketDetection", BooleanValue (true)); + Config::SetDefault ("ns3::Ipv4L3Protocol::DuplicateExpire", TimeValue (Seconds (10))); + + // Create topology + + // Create nodes + auto nodes = NodeContainer (); + nodes.Create (5); + + // Name nodes + Names::Add ("A", nodes.Get (0)); + Names::Add ("B", nodes.Get (1)); + Names::Add ("C", nodes.Get (2)); + Names::Add ("D", nodes.Get (3)); + Names::Add ("E", nodes.Get (4)); + + SimpleNetDeviceHelper simplenet; + auto devices = simplenet.Install (nodes); + // name devices + Names::Add ("A/dev", devices.Get (0)); + Names::Add ("B/dev", devices.Get (1)); + Names::Add ("C/dev", devices.Get (2)); + Names::Add ("D/dev", devices.Get (3)); + Names::Add ("E/dev", devices.Get (4)); + + // setup static routes to facilitate multicast flood + Ipv4ListRoutingHelper listRouting; + Ipv4StaticRoutingHelper staticRouting; + listRouting.Add (staticRouting, 0); + + InternetStackHelper internet; + internet.SetIpv6StackInstall (false); + internet.SetIpv4ArpJitter (true); + internet.SetRoutingHelper (listRouting); + internet.Install (nodes); + + Ipv4AddressHelper ipv4address; + ipv4address.SetBase ("10.0.0.0", "255.255.255.0"); + ipv4address.Assign (devices); + + // add static routes for each node / device + for (auto diter = devices.Begin (); diter != devices.End (); ++diter) + { + Ptr node = (*diter)->GetNode (); + + if (Names::FindName (node) == "A") + { + // route for host + // Use host routing entry according to note in Ipv4StaticRouting::RouteOutput: + //// Note: Multicast routes for outbound packets are stored in the + //// normal unicast table. An implication of this is that it is not + //// possible to source multicast datagrams on multiple interfaces. + //// This is a well-known property of sockets implementation on + //// many Unix variants. + //// So, we just log it and fall through to LookupStatic () + auto ipv4 = node->GetObject (); + NS_ASSERT_MSG ((bool) ipv4, "Node " << Names::FindName (node) << " does not have Ipv4 aggregate"); + auto routing = staticRouting.GetStaticRouting (ipv4); + routing->AddHostRouteTo (targetAddr.c_str (), ipv4->GetInterfaceForDevice (*diter), 0); + } + else + { + // route for forwarding + staticRouting.AddMulticastRoute (node, Ipv4Address::GetAny (), targetAddr.c_str (), *diter, NetDeviceContainer (*diter)); + } + } + + // set the topology, by default fully-connected + auto channel = devices.Get (0)->GetChannel (); + auto simplechannel = channel->GetObject (); + simplechannel->BlackList (Names::Find ("A/dev"), Names::Find ("D/dev")); + simplechannel->BlackList (Names::Find ("D/dev"), Names::Find ("A/dev")); + + simplechannel->BlackList (Names::Find ("A/dev"), Names::Find ("E/dev")); + simplechannel->BlackList (Names::Find ("E/dev"), Names::Find ("A/dev")); + + simplechannel->BlackList (Names::Find ("B/dev"), Names::Find ("E/dev")); + simplechannel->BlackList (Names::Find ("E/dev"), Names::Find ("B/dev")); + + simplechannel->BlackList (Names::Find ("C/dev"), Names::Find ("E/dev")); + simplechannel->BlackList (Names::Find ("E/dev"), Names::Find ("C/dev")); + // ensure some time progress between re-transmissions + simplechannel->SetAttribute ("Delay", TimeValue (MilliSeconds (1))); + + // sinks + PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 9)); + auto sinks = sinkHelper.Install ("B"); + sinks.Add (sinkHelper.Install ("C")); + sinks.Add (sinkHelper.Install ("D")); + sinks.Add (sinkHelper.Install ("E")); + sinks.Start (Seconds (1)); + + // source + OnOffHelper onoffHelper ("ns3::UdpSocketFactory", InetSocketAddress (targetAddr.c_str (), 9)); + onoffHelper.SetAttribute ("DataRate", DataRateValue (DataRate ("8Mbps"))); + onoffHelper.SetAttribute ("MaxBytes", UintegerValue (10 * 1024)); + auto source = onoffHelper.Install ("A"); + source.Start (Seconds (1.1)); + + // pcap traces + for (auto end = nodes.End (), + iter = nodes.Begin (); iter != end; ++iter) + { + internet.EnablePcapIpv4 ("smf-trace", (*iter)->GetId (), 1, false); + } + + // run simulation + Simulator::Run (); + + std::cout << "Node A sent " << 10 * 1024 << " bytes" << std::endl; + for (auto end = sinks.End (), + iter = sinks.Begin (); iter != end; ++iter) + { + auto node = (*iter)->GetNode (); + auto sink = (*iter)->GetObject (); + std::cout << "Node " << Names::FindName (node) + << " received " << sink->GetTotalRx () << " bytes" << std::endl; + } + + Simulator::Destroy (); + + Names::Clear (); + return 0; +} + diff --git a/examples/routing/wscript b/examples/routing/wscript index 597001bd6..d2cb2cf03 100644 --- a/examples/routing/wscript +++ b/examples/routing/wscript @@ -50,3 +50,7 @@ def build(bld): obj = bld.create_ns3_program('global-routing-multi-switch-plus-router', ['core', 'network', 'applications', 'internet', 'bridge', 'csma', 'point-to-point', 'csma', 'internet']) obj.source = 'global-routing-multi-switch-plus-router.cc' + + obj = bld.create_ns3_program('simple-multicast-flooding', + ['core', 'network', 'applications', 'internet']) + obj.source = 'simple-multicast-flooding.cc'