--- a/AUTHORS Tue Aug 25 08:52:57 2009 +0200
+++ b/AUTHORS Wed Aug 26 15:29:03 2009 +0400
@@ -1,16 +1,17 @@
-Kirill V. Andreev (kirillano@yandex.ru)
+Kirill Andreev (andreev@iitp.ru)
Nicola Baldo (nbaldo@cttc.es)
Mirko Banchi (mk.banchi@gmail.com)
Mehdi Benamor (mehdi.benamor@telecom-bretagne.eu)
Raj Bhattacharjea (raj.b@gatech.edu)
Timo Bingmann (timo.bingmann@student.kit.edu)
+Pavel Boyko (boyko@iitp.ru)
Gustavo Carneiro (gjc@inescporto.pt, gjcarneiro@gmail.com)
Angelos Chatzipapas (chatzipa@ceid.upatras.gr)
Luis Cortes (cortes@gatech.edu)
Craig Dowell (craigdo@ee.washington.edu)
David Gross (gdavid.devel@gmail.com)
Tom Henderson (tomhend@u.washington.edu)
-Andrey Hippo (ahippo@yandex.ru)
+Andrey Mazo (mazo@iitp.ru)
Sam Jansen (sam.jansen@gmail.com)
Liu Jian (liujatp@gmail.com)
Joe Kopena (tjkopena@cs.drexel.edu)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mesh.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/global-routing-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/mesh-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/mesh-helper.h"
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TestMeshScript");
+class MeshTest
+{
+ public:
+ /// Init test
+ MeshTest ();
+ /// Configure test from command line arguments
+ void Configure (int argc, char ** argv);
+ /// Run test
+ int Run ();
+ private:
+ int m_xSize;
+ int m_ySize;
+ double m_step;
+ double m_randomStart;
+ double m_totalTime;
+ double m_packetInterval;
+ uint16_t m_packetSize;
+ uint32_t m_nIfaces;
+ bool m_chan;
+ bool m_pcap;
+ std::string m_stack;
+ std::string m_root;
+ /// List of network nodes
+ NodeContainer nodes;
+ /// List of all mesh point devices
+ NetDeviceContainer meshDevices;
+ //Addresses of interfaces:
+ Ipv4InterfaceContainer interfaces;
+ // MeshHelper. Report is not static methods
+ MeshHelper mesh;
+ private:
+ /// Create nodes and setup their mobility
+ void CreateNodes ();
+ /// Install internet m_stack on nodes
+ void InstallInternetStack ();
+ /// Install applications
+ void InstallApplication ();
+ /// Print mesh devices diagnostics
+ void Report ();
+};
+MeshTest::MeshTest () :
+ m_xSize (3),
+ m_ySize (3),
+ m_step (100.0),
+ m_randomStart (0.1),
+ m_totalTime (100.0),
+ m_packetInterval (0.1),
+ m_packetSize (1024),
+ m_nIfaces (1),
+ m_chan (true),
+ m_pcap (false),
+ m_stack ("ns3::Dot11sStack"),
+ m_root ("ff:ff:ff:ff:ff:ff")
+{
+}
+void
+MeshTest::Configure (int argc, char *argv[])
+{
+ CommandLine cmd;
+ cmd.AddValue ("x-size", "Number of nodes in a row grid. [6]", m_xSize);
+ cmd.AddValue ("y-size", "Number of rows in a grid. [6]", m_ySize);
+ cmd.AddValue ("m_step", "Size of edge in our grid, meters. [100 m]", m_step);
+ cmd.AddValue ("start", "Maximum random start delay, seconds. [0.1 s]", m_randomStart);
+ cmd.AddValue ("time", "Simulation time, seconds [100 s]", m_totalTime);
+ cmd.AddValue ("packet-interval", "Interval between packets, seconds [0.001 s]", m_packetInterval);
+ cmd.AddValue ("packet-size", "Size of packets", m_packetSize);
+ cmd.AddValue ("interfaces", "Number of radio interfaces used by each mesh point. [1]", m_nIfaces);
+ cmd.AddValue ("m_channels", "Use different frequency m_channels for different interfaces. [0]", m_chan);
+ cmd.AddValue ("m_pcap", "Enable PCAP traces on interfaces. [0]", m_pcap);
+ cmd.AddValue ("m_stack", "Type of protocol m_stack. ns3::Dot11sStack by default", m_stack);
+ cmd.AddValue ("m_root", "Mac address of m_root mesh point", m_root);
+
+ cmd.Parse (argc, argv);
+ NS_LOG_DEBUG ("Grid:" << m_xSize << "*" << m_ySize);
+ NS_LOG_DEBUG ("Simulation time: " << m_totalTime << " s");
+}
+void
+MeshTest::CreateNodes ()
+{
+ nodes.Create (m_ySize*m_xSize);
+ // Setting m_channel
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+ wifiPhy.SetChannel (wifiChannel.Create ());
+ mesh = MeshHelper::Default ();
+ // Install mesh point devices & protocols
+ mesh.SetStackInstaller (m_stack, "Root", Mac48AddressValue (Mac48Address (m_root.c_str ())));
+ if (m_chan)
+ {
+ mesh.SetSpreadInterfaceChannels (MeshHelper::SPREAD_CHANNELS);
+ }
+ else
+ {
+ mesh.SetSpreadInterfaceChannels (MeshHelper::ZERO_CHANNEL);
+ }
+ //MeshInterfaceHelper interface = MeshInterfaceHelper::Default ();
+ mesh.SetMacType ("RandomStart", TimeValue (Seconds(m_randomStart)));
+ mesh.SetNumberOfInterfaces (m_nIfaces);
+ meshDevices = mesh.Install (wifiPhy, nodes);
+ // Setup mobility
+ MobilityHelper mobility;
+ mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
+ "MinX", DoubleValue (0.0),
+ "MinY", DoubleValue (0.0),
+ "DeltaX", DoubleValue (m_step),
+ "DeltaY", DoubleValue (m_step),
+ "GridWidth", UintegerValue (m_xSize),
+ "LayoutType", StringValue ("RowFirst"));
+ mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+ mobility.Install (nodes);
+ if (m_pcap)
+ wifiPhy.EnablePcapAll (std::string ("mp-"));
+}
+void
+MeshTest::InstallInternetStack ()
+{
+ InternetStackHelper m_stack;
+ m_stack.Install (nodes);
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.0");
+ interfaces = address.Assign (meshDevices);
+}
+void
+MeshTest::InstallApplication ()
+{
+ UdpEchoServerHelper echoServer (9);
+ ApplicationContainer serverApps = echoServer.Install (nodes.Get (0));
+ serverApps.Start (Seconds (0.0));
+ serverApps.Stop (Seconds (m_totalTime));
+ UdpEchoClientHelper echoClient (interfaces.GetAddress (0), 9);
+ echoClient.SetAttribute ("MaxPackets", UintegerValue ((uint32_t)(m_totalTime*(1/m_packetInterval))));
+ echoClient.SetAttribute ("Interval", TimeValue (Seconds (m_packetInterval)));
+ echoClient.SetAttribute ("PacketSize", UintegerValue (m_packetSize));
+ ApplicationContainer clientApps = echoClient.Install (nodes.Get (m_xSize*m_ySize-1));
+ clientApps.Start (Seconds (0.0));
+ clientApps.Stop (Seconds (m_totalTime));
+}
+int
+MeshTest::Run ()
+{
+ CreateNodes ();
+ InstallInternetStack ();
+ InstallApplication ();
+ Simulator::Schedule (Seconds(m_totalTime), & MeshTest::Report, this);
+ Simulator::Stop (Seconds (m_totalTime));
+ Simulator::Run ();
+ Simulator::Destroy ();
+ return 0;
+}
+void
+MeshTest::Report ()
+{
+ unsigned n (0);
+ for (NetDeviceContainer::Iterator i = meshDevices.Begin (); i != meshDevices.End (); ++i, ++n)
+ {
+ std::ostringstream os;
+ os << "mp-report-" << n << ".xml";
+ std::cerr << "Printing mesh point device #" << n << " diagnostics to " << os.str () << "\n";
+ std::ofstream of;
+ of.open (os.str().c_str());
+ if (! of.is_open ())
+ {
+ std::cerr << "Error: Can't open file " << os.str() << "\n";
+ return;
+ }
+ mesh.Report (*i, of);
+ of.close ();
+ }
+}
+int
+main (int argc, char *argv[])
+{
+ MeshTest t;
+ t.Configure (argc, argv);
+ return t.Run();
+}
--- a/examples/wscript Tue Aug 25 08:52:57 2009 +0200
+++ b/examples/wscript Wed Aug 26 15:29:03 2009 +0400
@@ -128,6 +128,10 @@
['core', 'simulator', 'mobility', 'wifi'])
obj.source = 'wifi-ap.cc'
+ obj = bld.create_ns3_program('mesh',
+ ['core', 'simulator', 'mobility', 'wifi'])
+ obj.source = 'mesh.cc'
+
bld.add_subdirs('stats')
obj = bld.create_ns3_program('wifi-wired-bridging',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/airtime-metric.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,95 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "airtime-metric.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/wifi-mode.h"
+namespace ns3 {
+namespace dot11s {
+NS_OBJECT_ENSURE_REGISTERED (AirtimeLinkMetricCalculator);
+TypeId
+AirtimeLinkMetricCalculator::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::AirtimeLinkMetricCalculator")
+ .SetParent<Object> ()
+ .AddConstructor<AirtimeLinkMetricCalculator> ()
+ .AddAttribute ( "OverheadNanosec",
+ "Overhead expressed in nanoseconds:DIFS+ 2* SIFS + 2* PREAMBLE + 2* ACK",
+ UintegerValue (108000),
+ MakeUintegerAccessor (&AirtimeLinkMetricCalculator::m_overheadNanosec),
+ MakeUintegerChecker<uint32_t> (1)
+ )
+ .AddAttribute ( "TestLength",
+ "Rate should be estimated using test length.",
+ UintegerValue (1024),
+ MakeUintegerAccessor (
+ &AirtimeLinkMetricCalculator::m_testLength),
+ MakeUintegerChecker<uint16_t> (1)
+ )
+ .AddAttribute ( "Dot11MacHeaderLength",
+ "Length of the 802.11 header",
+ UintegerValue (36),
+ MakeUintegerAccessor (
+ &AirtimeLinkMetricCalculator::m_headerLength),
+ MakeUintegerChecker<uint16_t> (0)
+ )
+ .AddAttribute ( "Dot11sMeshHeaderLength",
+ "Length of the mesh header",
+ UintegerValue (6),
+ MakeUintegerAccessor (
+ &AirtimeLinkMetricCalculator::m_meshHeaderLength),
+ MakeUintegerChecker<uint16_t> (0)
+ )
+ ;
+ return tid;
+}
+
+uint32_t
+AirtimeLinkMetricCalculator::CalculateMetric (Mac48Address peerAddress, Ptr<MeshWifiInterfaceMac> mac)
+{
+ /* Airtime link metric is defined in 11B.10 of 802.11s Draft D3.0 as:
+ *
+ * airtime = (O + Bt/r)* (1 + average retry counter), where
+ * o -- the PHY dependent channel access which includes frame headers, training sequences,
+ * access protocol frames, etc.
+ * bt -- the test packet length in bits (8192 by default),
+ * r -- the current bitrate of the packet,
+ *
+ * Final result is expressed in units of 0.01 Time Unit = 10.24 us (as required by 802.11s draft)
+ */
+
+ const double sec2ns = 1e9; // seconds -> nanoseconds conversion factor
+ const double ns2tu = 10240; // nanoseconds -> 0.01 TU conversion factor
+
+ WifiRemoteStation * station = mac->GetStationManager ()->Lookup (peerAddress);
+ NS_ASSERT (station != 0);
+ Ptr<Packet> test_frame = Create<Packet> (m_testLength + m_headerLength + m_meshHeaderLength);
+ uint32_t rate =
+ station->GetDataMode (test_frame, m_testLength + m_headerLength + m_meshHeaderLength).GetDataRate ();
+ uint32_t payload_nanosec = (uint32_t) (
+ (double) ((m_testLength + m_meshHeaderLength) * 8 /*octets -> bits*/) * sec2ns / ((double) rate));
+ uint32_t header_nanosec = (uint32_t) ((double) (m_headerLength * 8 /*octets -> bits*/* sec2ns)
+ / ((double) mac->GetStationManager () -> GetBasicMode (0).GetDataRate ()));
+ uint32_t metric = (uint32_t) (((double) (payload_nanosec + header_nanosec + m_overheadNanosec)) / ns2tu
+ * (station->GetAvgSlrc () + 1));
+ return metric;
+}
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/airtime-metric.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,59 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef AIRTIME_METRIC_H
+#define AIRTIME_METRIC_H
+#include "ns3/mesh-wifi-interface-mac.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief airtime link metric calculator
+ *
+ * \details Airtime link metric is defined in 11B.10 of 802.11s Draft D3.0 as:
+ *
+ * airtime = (O + Bt/r)* (1 + average retry counter), where
+ *
+ * o -- the PHY dependent channel access which includes frame headers, training sequences,
+ * access protocol frames, etc.
+ * bt -- the test packet length in bits (8192 by default),
+ * r -- the current bitrate of the packet,
+ *
+ * Final result is expressed in units of 0.01 Time Unit = 10.24 us (as required by 802.11s draft)
+ */
+class AirtimeLinkMetricCalculator : public Object
+{
+public:
+ static TypeId GetTypeId ();
+ uint32_t CalculateMetric (Mac48Address peerAddress, Ptr<MeshWifiInterfaceMac> mac);
+private:
+ //\brief Overhead expressed in nanoseconds:DIFS+ 2* SIFS + 2*PREAMBLE + 2* ACK
+ uint32_t m_overheadNanosec;
+ ///\brief Bt value
+ uint32_t m_testLength;
+ ///\brief header length (used in overhead)
+ uint16_t m_headerLength;
+ ///\brief meshHeader length (6 octets usually)
+ uint16_t m_meshHeaderLength;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-installer.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,124 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+#include "dot11s-installer.h"
+#include "peer-management-protocol.h"
+#include "hwmp-protocol.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+
+namespace ns3 {
+using namespace dot11s;
+NS_OBJECT_ENSURE_REGISTERED (Dot11sStack);
+TypeId
+Dot11sStack::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::Dot11sStack")
+ .SetParent<Object> ()
+ .AddConstructor<Dot11sStack> ()
+ .AddAttribute ("Root",
+ "The MAC address of root mesh point.",
+ Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
+ MakeMac48AddressAccessor (&Dot11sStack::m_root),
+ MakeMac48AddressChecker ());
+ return tid;
+}
+Dot11sStack::Dot11sStack () :
+ m_root (Mac48Address ("ff:ff:ff:ff:ff:ff"))
+{
+}
+Dot11sStack::~Dot11sStack ()
+{
+}
+void
+Dot11sStack::DoDispose ()
+{
+}
+bool
+Dot11sStack::InstallStack (Ptr<MeshPointDevice> mp)
+{
+ //Install Peer management protocol:
+ Ptr<PeerManagementProtocol> pmp = CreateObject<PeerManagementProtocol> ();
+ pmp->SetMeshId ("mesh");
+ bool install_ok = pmp->Install (mp);
+ if (!install_ok)
+ {
+ return false;
+ }
+ //Install HWMP:
+ Ptr<HwmpProtocol> hwmp = CreateObject<HwmpProtocol> ();
+ install_ok = hwmp->Install (mp);
+ if (!install_ok)
+ {
+ return false;
+ }
+ if (mp->GetAddress() == m_root)
+ {
+ hwmp->SetRoot ();
+ }
+ //Install interaction between HWMP and Peer management protocol:
+ pmp->SetPeerLinkStatusCallback (MakeCallback (&HwmpProtocol::PeerLinkStatus, hwmp));
+ hwmp->SetNeighboursCallback (MakeCallback (&PeerManagementProtocol::GetActiveLinks, pmp));
+ return true;
+}
+void
+Dot11sStack::Report (const Ptr<MeshPointDevice> mp, std::ostream& os)
+{
+ mp->Report (os);
+
+ std::vector<Ptr<NetDevice> > ifaces = mp->GetInterfaces ();
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i)
+ {
+ Ptr<WifiNetDevice> device = (*i)->GetObject<WifiNetDevice> ();
+ NS_ASSERT (device != 0);
+ Ptr<MeshWifiInterfaceMac> mac = device->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ NS_ASSERT (mac != 0);
+ mac->Report (os);
+ }
+ Ptr<HwmpProtocol> hwmp = mp->GetObject<HwmpProtocol> ();
+ NS_ASSERT (hwmp != 0);
+ hwmp->Report (os);
+
+ Ptr<PeerManagementProtocol> pmp = mp->GetObject<PeerManagementProtocol> ();
+ NS_ASSERT (pmp != 0);
+ pmp->Report (os);
+}
+void
+Dot11sStack::ResetStats (const Ptr<MeshPointDevice> mp)
+{
+ mp->ResetStats ();
+
+ std::vector<Ptr<NetDevice> > ifaces = mp->GetInterfaces ();
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i)
+ {
+ Ptr<WifiNetDevice> device = (*i)->GetObject<WifiNetDevice> ();
+ NS_ASSERT (device != 0);
+ Ptr<MeshWifiInterfaceMac> mac = device->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ NS_ASSERT (mac != 0);
+ mac->ResetStats ();
+ }
+ Ptr<HwmpProtocol> hwmp = mp->GetObject<HwmpProtocol> ();
+ NS_ASSERT (hwmp != 0);
+ hwmp->ResetStats ();
+
+ Ptr<PeerManagementProtocol> pmp = mp->GetObject<PeerManagementProtocol> ();
+ NS_ASSERT (pmp != 0);
+ pmp->ResetStats ();
+}
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-installer.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef DOT11S_STACK_INSTALLER_H
+#define DOT11S_STACK_INSTALLER_H
+#include "ns3/mesh-stack-installer.h"
+namespace ns3 {
+class Dot11sStack : public MeshStack
+{
+ public:
+ static TypeId GetTypeId ();
+ Dot11sStack ();
+ ~Dot11sStack ();
+ void DoDispose ();
+
+ ///\brief Installs 802.11s stack. needed by helper only
+ bool InstallStack (Ptr<MeshPointDevice> mp);
+ void Report (const Ptr<MeshPointDevice> mp, std::ostream&);
+ void ResetStats (const Ptr<MeshPointDevice> mp);
+ private:
+ Mac48Address m_root;
+};
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-mac-header.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,376 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#include "dot11s-mac-header.h"
+#include "ns3/packet.h"
+#include "ns3/test.h"
+
+namespace ns3 {
+namespace dot11s {
+/***********************************************************
+ * Here Mesh Mac Header functionality is defined.
+ ***********************************************************/
+TypeId
+MeshHeader::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::Dot11sMacHeader")
+ .SetParent<Header> ()
+ .AddConstructor<MeshHeader> ();
+ return tid;
+}
+MeshHeader::MeshHeader () :
+ m_meshFlags (0), m_meshTtl (0), m_meshSeqno (0), m_addr4 (Mac48Address ()), m_addr5 (Mac48Address ()),
+ m_addr6 (Mac48Address ())
+{
+}
+MeshHeader::~MeshHeader ()
+{
+}
+TypeId
+MeshHeader::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+void
+MeshHeader::SetAddr4 (Mac48Address address)
+{
+ m_addr4 = address;
+}
+void
+MeshHeader::SetAddr5 (Mac48Address address)
+{
+ m_addr5 = address;
+}
+void
+MeshHeader::SetAddr6 (Mac48Address address)
+{
+ m_addr6 = address;
+}
+Mac48Address
+MeshHeader::GetAddr4 () const
+{
+ return m_addr4;
+}
+Mac48Address
+MeshHeader::GetAddr5 () const
+{
+ return m_addr5;
+}
+Mac48Address
+MeshHeader::GetAddr6 () const
+{
+ return m_addr6;
+}
+void
+MeshHeader::SetMeshSeqno (uint32_t seqno)
+{
+ m_meshSeqno = seqno;
+}
+uint32_t
+MeshHeader::GetMeshSeqno () const
+{
+ return m_meshSeqno;
+}
+void
+MeshHeader::SetMeshTtl (uint8_t TTL)
+{
+ m_meshTtl = TTL;
+}
+uint8_t
+MeshHeader::GetMeshTtl () const
+{
+ return m_meshTtl;
+}
+void
+MeshHeader::SetAddressExt (uint8_t num_of_addresses)
+{
+ NS_ASSERT (num_of_addresses <= 3);
+ m_meshFlags |= 0x03 & num_of_addresses;
+}
+uint8_t
+MeshHeader::GetAddressExt () const
+{
+ return (0x03 & m_meshFlags);
+}
+uint32_t
+MeshHeader::GetSerializedSize () const
+{
+ return 6 + GetAddressExt () * 6;
+}
+void
+MeshHeader::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ i.WriteU8 (m_meshFlags);
+ i.WriteU8 (m_meshTtl);
+ i.WriteHtolsbU32 (m_meshSeqno);
+ uint8_t addresses_to_add = GetAddressExt ();
+ //Writing Address extensions:
+ if ((addresses_to_add == 1) || (addresses_to_add == 3))
+ {
+ WriteTo (i, m_addr4);
+ }
+ if (addresses_to_add > 1)
+ {
+ WriteTo (i, m_addr5);
+ }
+ if (addresses_to_add > 1)
+ {
+ WriteTo (i, m_addr6);
+ }
+}
+uint32_t
+MeshHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ uint8_t addresses_to_read = 0;
+ m_meshFlags = i.ReadU8 ();
+ m_meshTtl = i.ReadU8 ();
+ m_meshSeqno = i.ReadLsbtohU32 ();
+ addresses_to_read = m_meshFlags & 0x03;
+ if ((addresses_to_read == 1) || (addresses_to_read == 3))
+ {
+ ReadFrom (i, m_addr4);
+ }
+ if (addresses_to_read > 1)
+ {
+ ReadFrom (i, m_addr5);
+ }
+ if (addresses_to_read > 1)
+ {
+ ReadFrom (i, m_addr6);
+ }
+ return i.GetDistanceFrom (start);
+}
+void
+MeshHeader::Print (std::ostream &os) const
+{
+ os << "flags = " << (uint16_t) m_meshFlags << std::endl << "ttl = " << (uint16_t) m_meshTtl
+ << std::endl << "seqno = " << m_meshSeqno << std::endl<< "addr4 = " << m_addr4 << std::endl
+ << "addr5 = " << m_addr5 << std::endl << "addr6 = " << m_addr6 << std::endl;
+}
+bool
+operator== (const MeshHeader & a, const MeshHeader & b)
+{
+ return ((a.m_meshFlags == b.m_meshFlags) && (a.m_meshTtl == b.m_meshTtl)
+ && (a.m_meshSeqno == b.m_meshSeqno) && (a.m_addr4 == b.m_addr4) && (a.m_addr5 == b.m_addr5)
+ && (a.m_addr6 == b.m_addr6));
+}
+/**********************************************************
+ * ActionFrame
+ **********************************************************/
+WifiMeshActionHeader::WifiMeshActionHeader ()
+{
+}
+WifiMeshActionHeader::~WifiMeshActionHeader ()
+{
+}
+void
+WifiMeshActionHeader::SetAction (WifiMeshActionHeader::CategoryValue type,
+ WifiMeshActionHeader::ActionValue action)
+{
+ m_category = type;
+
+ switch (type)
+ {
+ case MESH_PEERING_MGT:
+ {
+ m_actionValue = action.peerLink;
+ break;
+ }
+ case MESH_PATH_SELECTION:
+ {
+ m_actionValue = action.pathSelection;
+ break;
+ }
+ case MESH_LINK_METRIC:
+ case MESH_INTERWORKING:
+ case MESH_RESOURCE_COORDINATION:
+ case MESH_PROXY_FORWARDING:
+ break;
+ }
+}
+WifiMeshActionHeader::CategoryValue
+WifiMeshActionHeader::GetCategory ()
+{
+ switch (m_category)
+ {
+ case MESH_PEERING_MGT:
+ return MESH_PEERING_MGT;
+ case MESH_LINK_METRIC:
+ return MESH_LINK_METRIC;
+ case MESH_PATH_SELECTION:
+ return MESH_PATH_SELECTION;
+ case MESH_INTERWORKING:
+ return MESH_INTERWORKING;
+ case MESH_RESOURCE_COORDINATION:
+ return MESH_RESOURCE_COORDINATION;
+ case MESH_PROXY_FORWARDING:
+ return MESH_PROXY_FORWARDING;
+ default:
+ NS_FATAL_ERROR ("Unknown action value");
+ return MESH_PEERING_MGT;
+ }
+}
+WifiMeshActionHeader::ActionValue
+WifiMeshActionHeader::GetAction ()
+{
+ ActionValue retval;
+ switch (m_category)
+ {
+ case MESH_PEERING_MGT:
+ switch (m_actionValue)
+ {
+ case PEER_LINK_OPEN:
+ retval.peerLink = PEER_LINK_OPEN;
+ return retval;
+ case PEER_LINK_CONFIRM:
+ retval.peerLink = PEER_LINK_CONFIRM;
+ return retval;
+ case PEER_LINK_CLOSE:
+ retval.peerLink = PEER_LINK_CLOSE;
+ return retval;
+ default:
+ NS_FATAL_ERROR ("Unknown mesh peering management action code");
+ return retval;
+ }
+ case MESH_PATH_SELECTION:
+ switch (m_actionValue)
+ {
+ case PATH_SELECTION:
+ retval.pathSelection = PATH_SELECTION;
+ return retval;
+ default:
+ NS_FATAL_ERROR ("Unknown mesh path selection action code");
+ return retval;
+ }
+ case MESH_LINK_METRIC:
+ // not yet supported
+ case MESH_INTERWORKING:
+ // not yet supported
+ case MESH_RESOURCE_COORDINATION:
+ // not yet supported
+ default:
+ NS_FATAL_ERROR ("Unsupported mesh action");
+ return retval;
+ }
+}
+TypeId
+WifiMeshActionHeader::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::WifiMeshActionHeader")
+ .SetParent<Header> ()
+ .AddConstructor<WifiMeshActionHeader> ();
+ return tid;
+}
+TypeId
+WifiMeshActionHeader::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+void
+WifiMeshActionHeader::Print (std::ostream &os) const
+{
+}
+uint32_t
+WifiMeshActionHeader::GetSerializedSize () const
+{
+ return 2;
+}
+void
+WifiMeshActionHeader::Serialize (Buffer::Iterator start) const
+{
+ start.WriteU8 (m_category);
+ start.WriteU8 (m_actionValue);
+}
+uint32_t
+WifiMeshActionHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ m_category = i.ReadU8 ();
+ m_actionValue = i.ReadU8 ();
+ return i.GetDistanceFrom (start);
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for Dot11sMacHeader
+struct Dot11sMacHeaderBist : public Test
+{
+ Dot11sMacHeaderBist () :
+ Test ("Mesh/802.11s/MeshHeader")
+ {
+ }
+ virtual bool
+ RunTests ();
+};
+
+/// Test instance
+static Dot11sMacHeaderBist g_Dot11sMacHeaderBist;
+
+bool
+Dot11sMacHeaderBist::RunTests ()
+{
+ bool result (true);
+ {
+ MeshHeader a;
+ a.SetAddressExt (3);
+ a.SetAddr4 (Mac48Address ("11:22:33:44:55:66"));
+ a.SetAddr5 (Mac48Address ("11:00:33:00:55:00"));
+ a.SetAddr6 (Mac48Address ("00:22:00:44:00:66"));
+ a.SetMeshTtl (122);
+ a.SetMeshSeqno (321);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ MeshHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ MeshHeader a;
+ a.SetAddressExt (2);
+ a.SetAddr5 (Mac48Address ("11:00:33:00:55:00"));
+ a.SetAddr6 (Mac48Address ("00:22:00:44:00:66"));
+ a.SetMeshTtl (122);
+ a.SetMeshSeqno (321);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ MeshHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ MeshHeader a;
+ a.SetAddressExt (1);
+ a.SetAddr4 (Mac48Address ("11:22:33:44:55:66"));
+ a.SetMeshTtl (122);
+ a.SetMeshSeqno (321);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ MeshHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ return result;
+}
+#endif
+} //namespace dot11s
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s-mac-header.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef MESH_WIFI_MAC_HEADER_H
+#define MESH_WIFI_MAC_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/mac48-address.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Mesh Control field, see IEEE 802.11s draft 3.0 section 7.1.3.5b
+ *
+ * Header format: | Mesh flags: 1 | TTL: 1 | Sequence number: 4 | Address ext.: 0, 6, 12 or 18 |
+ */
+class MeshHeader : public Header
+{
+public:
+ MeshHeader ();
+ ~MeshHeader ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual void Print (std::ostream &os) const;
+
+ void SetAddr4 (Mac48Address address);
+ void SetAddr5 (Mac48Address address);
+ void SetAddr6 (Mac48Address address);
+ Mac48Address GetAddr4 () const;
+ Mac48Address GetAddr5 () const;
+ Mac48Address GetAddr6 () const;
+
+ void SetMeshSeqno (uint32_t seqno);
+ uint32_t GetMeshSeqno () const;
+
+ void SetMeshTtl (uint8_t TTL);
+ uint8_t GetMeshTtl () const;
+
+ void SetAddressExt (uint8_t num_of_addresses);
+ uint8_t GetAddressExt () const;
+
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+private:
+ uint8_t m_meshFlags;
+ uint8_t m_meshTtl;
+ uint32_t m_meshSeqno;
+ Mac48Address m_addr4;
+ Mac48Address m_addr5;
+ Mac48Address m_addr6;
+ friend bool operator== (const MeshHeader & a, const MeshHeader & b);
+};
+bool operator== (const MeshHeader & a, const MeshHeader & b);
+
+/**
+ * \ingroup dot11s
+ *
+ * \brief See IEEE 802.11s draft 3.0 section 7.2.3.14
+ *
+ * Header format: | category: 1 | action value: 1 |
+ */
+class WifiMeshActionHeader : public Header
+{
+public:
+ WifiMeshActionHeader ();
+ ~WifiMeshActionHeader ();
+
+ /* Compatible with open80211s implementation */
+ enum CategoryValue //table 7-24 staring from 4
+ {
+ MESH_PEERING_MGT = 30,
+ MESH_LINK_METRIC = 31,
+ MESH_PATH_SELECTION = 32,
+ MESH_INTERWORKING = 33,
+ MESH_RESOURCE_COORDINATION = 34,
+ MESH_PROXY_FORWARDING = 35,
+ };
+ /* Compatible with open80211s implementation */
+ enum PeerLinkMgtActionValue
+ {
+ PEER_LINK_OPEN = 0,
+ PEER_LINK_CONFIRM = 1,
+ PEER_LINK_CLOSE = 2,
+ };
+ enum LinkMetricActionValue
+ {
+ LINK_METRIC_REQUEST = 0,
+ LINK_METRIC_REPORT,
+ };
+ /* Compatible with open80211s implementation */
+ enum PathSelectionActionValue
+ {
+ PATH_SELECTION = 0,
+ };
+ enum InterworkActionValue
+ {
+ PORTAL_ANNOUNCEMENT = 0,
+ };
+ enum ResourceCoordinationActionValue
+ {
+ CONGESTION_CONTROL_NOTIFICATION = 0,
+ MDA_SETUP_REQUEST,
+ MDA_SETUP_REPLY,
+ MDAOP_ADVERTISMENT_REQUEST,
+ MDAOP_ADVERTISMENTS,
+ MDAOP_SET_TEARDOWN,
+ BEACON_TIMING_REQUEST,
+ BEACON_TIMING_RESPONSE,
+ TBTT_ADJUSTMENT_REQUEST,
+ MESH_CHANNEL_SWITCH_ANNOUNCEMENT,
+ };
+ typedef union
+ {
+ enum PeerLinkMgtActionValue peerLink;
+ enum LinkMetricActionValue linkMetrtic;
+ enum PathSelectionActionValue pathSelection;
+ enum InterworkActionValue interwork;
+ enum ResourceCoordinationActionValue resourceCoordination;
+ } ActionValue;
+ void SetAction (enum CategoryValue type,ActionValue action);
+
+ CategoryValue GetCategory ();
+ ActionValue GetAction ();
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+private:
+ uint8_t m_category;
+ uint8_t m_actionValue;
+};
+} //namespace dot11s
+} // namespace ns3
+#endif /* MESH_WIFI_MAC_HEADER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/dot11s.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,34 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ *
+ * This is doxygen module description, don't include
+ */
+/**
+ * \ingroup mesh
+ * \defgroup dot11s IEEE 802.11s draft
+ *
+ * \brief IEEE 802.11s (mesh) draft standard implementation
+ *
+ * Current model conforms IEEE 802.11s D3.0 draft version and includes
+ * Peer Management Protocol and HWMP (routing) Protocol implementations.
+ *
+ * The multi-interface (aka multi radio) mesh points are supported as an
+ * extensions of ieee draft version 3.0. Note that corresponding helper
+ * creates single interface station by default.
+ */
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-protocol-mac.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,476 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/log.h"
+#include "dot11s-mac-header.h"
+#include "hwmp-protocol.h"
+#include "hwmp-protocol-mac.h"
+#include "hwmp-tag.h"
+#include "ie-dot11s-preq.h"
+#include "ie-dot11s-prep.h"
+#include "ie-dot11s-rann.h"
+
+namespace ns3 {
+namespace dot11s {
+
+NS_LOG_COMPONENT_DEFINE ("HwmpProtocolMac");
+HwmpProtocolMac::HwmpProtocolMac (uint32_t ifIndex, Ptr<HwmpProtocol> protocol) :
+ m_ifIndex (ifIndex), m_protocol (protocol)
+{
+}
+HwmpProtocolMac::~HwmpProtocolMac ()
+{
+}
+void
+HwmpProtocolMac::SetParent (Ptr<MeshWifiInterfaceMac> parent)
+{
+ m_parent = parent;
+}
+
+bool
+HwmpProtocolMac::ReceiveData (Ptr<Packet> packet, const WifiMacHeader & header)
+{
+ NS_ASSERT (header.IsData ());
+
+ MeshHeader meshHdr;
+ HwmpTag tag;
+ if (packet->PeekPacketTag (tag))
+ {
+ NS_FATAL_ERROR ("HWMP tag is not supposed to be received by network");
+ }
+
+ packet->RemoveHeader (meshHdr);
+ m_stats.rxData++;
+ m_stats.rxDataBytes += packet->GetSize ();
+
+ //TODO: address extension
+ Mac48Address destination;
+ Mac48Address source;
+ switch (meshHdr.GetAddressExt ())
+ {
+ case 0:
+ source = header.GetAddr4 ();
+ destination = header.GetAddr3 ();
+ break;
+ default:
+ NS_FATAL_ERROR (
+ "6-address scheme is not yet supported and 4-address extension is not supposed to be used for data frames.");
+ }
+ tag.SetSeqno (meshHdr.GetMeshSeqno ());
+ tag.SetTtl (meshHdr.GetMeshTtl ());
+ packet->AddPacketTag (tag);
+
+ if ((destination == Mac48Address::GetBroadcast ()) && (m_protocol->DropDataFrame (meshHdr.GetMeshSeqno (),
+ source)))
+ {
+ return false;
+ }
+ return true;
+}
+
+bool
+HwmpProtocolMac::ReceiveAction (Ptr<Packet> packet, const WifiMacHeader & header)
+{
+ m_stats.rxMgt++;
+ m_stats.rxMgtBytes += packet->GetSize ();
+ WifiMeshActionHeader actionHdr;
+ packet->RemoveHeader (actionHdr);
+ WifiMeshActionHeader::ActionValue actionValue = actionHdr.GetAction ();
+ if (actionHdr.GetCategory () != WifiMeshActionHeader::MESH_PATH_SELECTION)
+ {
+ return true;
+ }
+ WifiInformationElementVector elements;
+ packet->RemoveHeader (elements);
+ std::vector<IePerr::FailedDestination> failedDestinations;
+ for (WifiInformationElementVector::Iterator i = elements.Begin(); i != elements.End(); i ++)
+ {
+ if ((*i)->ElementId () == IE11S_RANN)
+ {
+ NS_LOG_WARN ("RANN is not supported!");
+ }
+ if ((*i)->ElementId () == IE11S_PREQ)
+ {
+ Ptr<IePreq> preq = DynamicCast<IePreq> (*i);
+ NS_ASSERT (preq != 0);
+ m_stats.rxPreq++;
+ if (preq->GetOriginatorAddress () == m_protocol->GetAddress ())
+ {
+ continue;
+ }
+ if (preq->GetTtl () == 0)
+ {
+ continue;
+ }
+ preq->DecrementTtl ();
+ m_protocol->ReceivePreq (*preq, header.GetAddr2 (), m_ifIndex, header.GetAddr3 (),
+ m_parent->GetLinkMetric (header.GetAddr2 ()));
+ }
+ if ((*i)->ElementId () == IE11S_PREP)
+ {
+ Ptr<IePrep> prep = DynamicCast<IePrep> (*i);
+ NS_ASSERT (prep != 0);
+ m_stats.rxPrep++;
+ if (prep->GetTtl () == 0)
+ {
+ continue;
+ }
+ prep->DecrementTtl ();
+ m_protocol->ReceivePrep (*prep, header.GetAddr2 (), m_ifIndex, header.GetAddr3 (),
+ m_parent->GetLinkMetric (header.GetAddr2 ()));
+ }
+ if ((*i)->ElementId () == IE11S_PERR)
+ {
+ Ptr<IePerr> perr = DynamicCast<IePerr> (*i);
+ NS_ASSERT (perr != 0);
+ m_stats.rxPerr++;
+ std::vector<IePerr::FailedDestination> destinations = perr->GetAddressUnitVector ();
+ for (std::vector<IePerr::FailedDestination>::const_iterator i = destinations.begin (); i
+ != destinations.end (); i++)
+ {
+ failedDestinations.push_back (*i);
+ }
+ }
+ }
+ if (failedDestinations.size () > 0)
+ {
+ m_protocol->ReceivePerr (failedDestinations, header.GetAddr2 (), m_ifIndex, header.GetAddr3 ());
+ }
+ NS_ASSERT (packet->GetSize () == 0);
+ return false;
+}
+
+bool
+HwmpProtocolMac::Receive (Ptr<Packet> packet, const WifiMacHeader & header)
+{
+ if (header.IsData ())
+ {
+ return ReceiveData (packet, header);
+ }
+ else
+ {
+ if (header.IsAction ())
+ {
+ return ReceiveAction (packet, header);
+ }
+ else
+ {
+ return true; // don't care
+ }
+ }
+}
+bool
+HwmpProtocolMac::UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from,
+ Mac48Address to)
+{
+ if (!header.IsData ())
+ {
+ return true;
+ }
+ HwmpTag tag;
+ bool tagExists = packet->RemovePacketTag (tag);
+ if (!tagExists)
+ {
+ NS_FATAL_ERROR ("HWMP tag must exist at this point");
+ }
+ m_stats.txData++;
+ m_stats.txDataBytes += packet->GetSize ();
+ MeshHeader meshHdr;
+ meshHdr.SetMeshSeqno (tag.GetSeqno ());
+ meshHdr.SetMeshTtl (tag.GetTtl ());
+ packet->AddHeader (meshHdr);
+ header.SetAddr1 (tag.GetAddress ());
+ return true;
+}
+WifiMeshActionHeader
+HwmpProtocolMac::GetWifiMeshActionHeader ()
+{
+ WifiMeshActionHeader actionHdr;
+ WifiMeshActionHeader::ActionValue action;
+ action.pathSelection = WifiMeshActionHeader::PATH_SELECTION;
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PATH_SELECTION, action);
+ return actionHdr;
+}
+void
+HwmpProtocolMac::SendPreq (IePreq preq)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ std::vector<IePreq> preq_vector;
+ preq_vector.push_back (preq);
+ SendPreq (preq_vector);
+}
+void
+HwmpProtocolMac::SendPreq (std::vector<IePreq> preq)
+{
+ Ptr<Packet> packet = Create<Packet> ();
+ WifiInformationElementVector elements;
+ for (std::vector<IePreq>::iterator i = preq.begin (); i != preq.end (); i++)
+ {
+ elements.AddInformationElement(Ptr<IePreq> (&(*i)));
+ }
+ packet->AddHeader(elements);
+ packet->AddHeader (GetWifiMeshActionHeader ());
+ //create 802.11 header:
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (m_protocol->GetAddress ());
+ //Send Management frame
+ std::vector<Mac48Address> receivers = m_protocol->GetPreqReceivers (m_ifIndex);
+ for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i++)
+ {
+ hdr.SetAddr1 (*i);
+ m_stats.txPreq++;
+ m_stats.txMgt++;
+ m_stats.txMgtBytes += packet->GetSize ();
+ m_parent->SendManagementFrame (packet, hdr);
+ }
+}
+void
+HwmpProtocolMac::RequestDestination (Mac48Address dst, uint32_t originator_seqno, uint32_t dst_seqno)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (std::vector<IePreq>::iterator i = m_myPreq.begin (); i != m_myPreq.end (); i++)
+ {
+ if (i->IsFull ())
+ {
+ continue;
+ }
+ NS_ASSERT (i->GetDestCount () > 0);
+ i->AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRfFlag (), dst, dst_seqno);
+ }
+ IePreq preq;
+ preq.SetHopcount (0);
+ preq.SetTTL (m_protocol->GetMaxTtl ());
+ preq.SetPreqID (m_protocol->GetNextPreqId ());
+ preq.SetOriginatorAddress (m_protocol->GetAddress ());
+ preq.SetOriginatorSeqNumber (originator_seqno);
+ preq.SetLifetime (m_protocol->GetActivePathLifetime ());
+ preq.AddDestinationAddressElement (m_protocol->GetDoFlag (), m_protocol->GetRfFlag (), dst, dst_seqno);
+ m_myPreq.push_back (preq);
+ SendMyPreq ();
+}
+void
+HwmpProtocolMac::SendMyPreq ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_preqTimer.IsRunning ())
+ {
+ return;
+ }
+ if (m_myPreq.size () == 0)
+ {
+ return;
+ }
+ //reschedule sending PREQ
+ NS_ASSERT (!m_preqTimer.IsRunning ());
+ m_preqTimer = Simulator::Schedule (m_protocol->GetPreqMinInterval (), &HwmpProtocolMac::SendMyPreq, this);
+ SendPreq (m_myPreq);
+ m_myPreq.clear ();
+}
+void
+HwmpProtocolMac::SendPrep (IePrep prep, Mac48Address receiver)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ //Create packet
+ Ptr<Packet> packet = Create<Packet> ();
+ WifiInformationElementVector elements;
+ elements.AddInformationElement(Ptr<IePrep> (&prep));
+ packet->AddHeader (elements);
+ packet->AddHeader (GetWifiMeshActionHeader ());
+ //create 802.11 header:
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ hdr.SetAddr1 (receiver);
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (m_protocol->GetAddress ());
+ //Send Management frame
+ m_stats.txPrep++;
+ m_stats.txMgt++;
+ m_stats.txMgtBytes += packet->GetSize ();
+ m_parent->SendManagementFrame (packet, hdr);
+}
+void
+HwmpProtocolMac::ForwardPerr (std::vector<IePerr::FailedDestination> failedDestinations, std::vector<
+ Mac48Address> receivers)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ Ptr<Packet> packet = Create<Packet> ();
+ Ptr<IePerr> perr = Create <IePerr> ();
+ WifiInformationElementVector elements;
+ for (std::vector<IePerr::FailedDestination>::const_iterator i = failedDestinations.begin (); i
+ != failedDestinations.end (); i++)
+ {
+ if (!perr->IsFull ())
+ {
+ perr->AddAddressUnit (*i);
+ }
+ else
+ {
+ elements.AddInformationElement(perr);
+ perr->ResetPerr ();
+ }
+ }
+ if (perr->GetNumOfDest () > 0)
+ {
+ elements.AddInformationElement(perr);
+ }
+ packet->AddHeader (elements);
+ packet->AddHeader (GetWifiMeshActionHeader ());
+ //create 802.11 header:
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ hdr.SetAddr3 (m_protocol->GetAddress ());
+ if (receivers.size () >= m_protocol->GetUnicastPerrThreshold ())
+ {
+ receivers.clear ();
+ receivers.push_back (Mac48Address::GetBroadcast ());
+ }
+ //Send Management frame
+ for (std::vector<Mac48Address>::const_iterator i = m_myPerr.receivers.begin (); i
+ != m_myPerr.receivers.end (); i++)
+ {
+ hdr.SetAddr1 (*i);
+ m_stats.txPerr++;
+ m_stats.txMgt++;
+ m_stats.txMgtBytes += packet->GetSize ();
+ m_parent->SendManagementFrame (packet, hdr);
+ }
+}
+void
+HwmpProtocolMac::InitiatePerr (std::vector<IePerr::FailedDestination> failedDestinations, std::vector<
+ Mac48Address> receivers)
+{
+ //All duplicates in PERR are checked here, and there is no reason to
+ //check it at any athoer place
+ {
+ std::vector<Mac48Address>::const_iterator end = receivers.end ();
+ for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != end; i++)
+ {
+ bool should_add = true;
+ for (std::vector<Mac48Address>::const_iterator j = m_myPerr.receivers.begin (); j
+ != m_myPerr.receivers.end (); j++)
+ {
+ if ((*i) == (*j))
+ {
+ should_add = false;
+ }
+ }
+ if (should_add)
+ {
+ m_myPerr.receivers.push_back (*i);
+ }
+ }
+ }
+ {
+ std::vector<IePerr::FailedDestination>::const_iterator end = failedDestinations.end ();
+ for (std::vector<IePerr::FailedDestination>::const_iterator i = failedDestinations.begin (); i != end; i++)
+ {
+ bool should_add = true;
+ for (std::vector<IePerr::FailedDestination>::const_iterator j = m_myPerr.destinations.begin (); j
+ != m_myPerr.destinations.end (); j++)
+ {
+ if (((*i).destination == (*j).destination) && ((*j).seqnum > (*i).seqnum))
+ {
+ should_add = false;
+ }
+ }
+ if (should_add)
+ {
+ m_myPerr.destinations.push_back (*i);
+ }
+ }
+ }
+ SendMyPerr ();
+}
+void
+HwmpProtocolMac::SendMyPerr ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ if (m_perrTimer.IsRunning ())
+ {
+ return;
+ }
+ m_perrTimer = Simulator::Schedule (m_protocol->GetPerrMinInterval (), &HwmpProtocolMac::SendMyPerr, this);
+ ForwardPerr (m_myPerr.destinations, m_myPerr.receivers);
+ m_myPerr.destinations.clear ();
+ m_myPerr.receivers.clear ();
+}
+uint32_t
+HwmpProtocolMac::GetLinkMetric (Mac48Address peerAddress) const
+{
+ return m_parent->GetLinkMetric (peerAddress);
+}
+uint16_t
+HwmpProtocolMac::GetChannelId () const
+{
+ return m_parent->GetFrequencyChannel ();
+}
+HwmpProtocolMac::Statistics::Statistics () :
+ txPreq (0), rxPreq (0), txPrep (0), rxPrep (0), txPerr (0), rxPerr (0), txMgt (0), txMgtBytes (0),
+ rxMgt (0), rxMgtBytes (0), txData (0), txDataBytes (0), rxData (0), rxDataBytes (0)
+{
+}
+void
+HwmpProtocolMac::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "txPreq= \"" << txPreq << "\"" << std::endl <<
+ "txPrep=\"" << txPrep << "\"" << std::endl <<
+ "txPerr=\"" << txPerr << "\"" << std::endl <<
+ "rxPreq=\"" << rxPreq << "\"" << std::endl <<
+ "rxPrep=\"" << rxPrep << "\"" << std::endl <<
+ "rxPerr=\"" << rxPerr << "\"" << std::endl <<
+ "txMgt=\"" << txMgt << "\"" << std::endl <<
+ "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl <<
+ "rxMgt=\"" << rxMgt << "\"" << std::endl <<
+ "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl <<
+ "txData=\"" << txData << "\"" << std::endl <<
+ "txDataBytes=\"" << txDataBytes << "\"" << std::endl <<
+ "rxData=\"" << rxData << "\"" << std::endl <<
+ "rxDataBytes=\"" << rxDataBytes << "\"/>" << std::endl;
+}
+void
+HwmpProtocolMac::Report (std::ostream & os) const
+{
+ os << "<HwmpProtocolMac" << std::endl <<
+ "address =\"" << m_parent->GetAddress () << "\">" << std::endl;
+ m_stats.Print (os);
+ os << "</HwmpProtocolMac>" << std::endl;
+}
+void
+HwmpProtocolMac::ResetStats ()
+{
+ m_stats = Statistics::Statistics ();
+}
+
+} //namespace dot11s
+}//namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-protocol-mac.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef HWMP_STATE_H
+#define HWMP_STATE_H
+
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+#include "ie-dot11s-preq.h"
+#include "ie-dot11s-perr.h"
+
+namespace ns3 {
+
+class MeshWifiInterfaceMac;
+
+namespace dot11s {
+
+class HwmpProtocol;
+class WifiMeshActionHeader;
+class IePreq;
+class IePrep;
+class IePerr;
+
+/**
+ * \ingroup dot11s
+ *
+ * \brief Interface MAC plugin for HWMP -- 802.11s routing protocol
+ */
+class HwmpProtocolMac : public MeshWifiInterfaceMacPlugin
+{
+public:
+ HwmpProtocolMac (uint32_t, Ptr<HwmpProtocol>);
+ ~HwmpProtocolMac ();
+ ///\name Inherited from MAC plugin
+ //\{
+ void SetParent (Ptr<MeshWifiInterfaceMac> parent);
+ bool Receive (Ptr<Packet> packet, const WifiMacHeader & header);
+ bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to);
+ /// Update beacon is empty, because HWMP does not know anything about beacons
+ void UpdateBeacon (MeshWifiBeacon & beacon) const {};
+ //\}
+
+private:
+ friend class HwmpProtocol;
+ ///\returns a path selection action header
+ static WifiMeshActionHeader GetWifiMeshActionHeader ();
+ ///\name Intercation with HWMP:
+ //\{
+ void SendPreq (IePreq preq);
+ void SendPreq (std::vector<IePreq> preq);
+ void SendPrep (IePrep prep, Mac48Address receiver);
+ //Forward a peth error
+ void ForwardPerr (std::vector<IePerr::FailedDestination> destinations, std::vector<Mac48Address> receivers);
+ // initiate my own path error
+ void InitiatePerr (std::vector<IePerr::FailedDestination> destinations, std::vector<Mac48Address> receivers);
+ /** \brief Request a destination. If can not send preq immediately -
+ * add a destination to exisying PREQ generated by me and stored in
+ * PREQ queue
+ * \param originator_seqno is a sequence number that shall be preq originator sequenece number
+ * \param dst_seqno is a sequence number taken from routing table
+ */
+ void RequestDestination (Mac48Address dest, uint32_t originator_seqno, uint32_t dst_seqno);
+ //\}
+
+ /// Sends one PREQ when PreqMinInterval after last PREQ expires (if any PREQ exists in rhe queue)
+ void SendMyPreq ();
+ void SendMyPerr ();
+ /// \return metric to HWMP protocol, needed only by metrics to add
+ //peer as routing entry
+ uint32_t GetLinkMetric (Mac48Address peerAddress) const;
+ uint16_t GetChannelId () const;
+ /// Report statistics
+ void Report (std::ostream &) const;
+ void ResetStats ();
+private:
+ Ptr<MeshWifiInterfaceMac> m_parent;
+ uint32_t m_ifIndex;
+ Ptr<HwmpProtocol> m_protocol;
+
+ ///\name my PREQ and PREQ timer:
+ //\{
+ EventId m_preqTimer;
+ std::vector<IePreq> m_myPreq;
+ //\}
+ ///\name PERR timer and stored path error
+ //\{
+ EventId m_perrTimer;
+ struct MyPerr {
+ std::vector<IePerr::FailedDestination> destinations;
+ std::vector<Mac48Address> receivers;
+ };
+ MyPerr m_myPerr;
+ ///\name Statistics:
+ //\{
+ struct Statistics
+ {
+ uint16_t txPreq;
+ uint16_t rxPreq;
+ uint16_t txPrep;
+ uint16_t rxPrep;
+ uint16_t txPerr;
+ uint16_t rxPerr;
+ uint16_t txMgt;
+ uint32_t txMgtBytes;
+ uint16_t rxMgt;
+ uint32_t rxMgtBytes;
+ uint16_t txData;
+ uint32_t txDataBytes;
+ uint16_t rxData;
+ uint32_t rxDataBytes;
+ void Print (std::ostream & os) const;
+ Statistics ();
+ };
+ Statistics m_stats;
+ //\}
+private:
+ /// Receive data frame
+ bool ReceiveData (Ptr<Packet> packet, const WifiMacHeader & header);
+ /// Receive action management frame
+ bool ReceiveAction (Ptr<Packet> packet, const WifiMacHeader & header);
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-protocol.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,1149 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "hwmp-protocol.h"
+#include "hwmp-protocol-mac.h"
+#include "hwmp-tag.h"
+#include "hwmp-rtable.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/random-variable.h"
+#include "airtime-metric.h"
+#include "ie-dot11s-preq.h"
+#include "ie-dot11s-prep.h"
+
+NS_LOG_COMPONENT_DEFINE ("HwmpProtocol");
+
+namespace ns3 {
+namespace dot11s {
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpProtocol);
+TypeId
+HwmpProtocol::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::HwmpProtocol")
+ .SetParent<MeshL2RoutingProtocol> ()
+ .AddConstructor<HwmpProtocol> ()
+ .AddAttribute ( "RandomStart",
+ "Random delay at first proactive PREQ",
+ TimeValue (Seconds (0.1)),
+ MakeTimeAccessor (
+ &HwmpProtocol::m_randomStart),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "MaxQueueSize",
+ "Maximum number of packets we can store when resolving route",
+ UintegerValue (255),
+ MakeUintegerAccessor (
+ &HwmpProtocol::m_maxQueueSize),
+ MakeUintegerChecker<uint16_t> (1)
+ )
+ .AddAttribute ( "Dot11MeshHWMPmaxPREQretries",
+ "Maximum number of retries before we suppose the destination to be unreachable",
+ UintegerValue (3),
+ MakeUintegerAccessor (
+ &HwmpProtocol::m_dot11MeshHWMPmaxPREQretries),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ( "Dot11MeshHWMPnetDiameterTraversalTime",
+ "Time we suppose the packet to go from one edge of the network to another",
+ TimeValue (MicroSeconds (1024*100)),
+ MakeTimeAccessor (
+ &HwmpProtocol::m_dot11MeshHWMPnetDiameterTraversalTime),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "Dot11MeshHWMPpreqMinInterval",
+ "Minimal interval between to successive PREQs",
+ TimeValue (MicroSeconds (1024*100)),
+ MakeTimeAccessor (
+ &HwmpProtocol::m_dot11MeshHWMPpreqMinInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "Dot11MeshHWMPperrMinInterval",
+ "Minimal interval between to successive PREQs",
+ TimeValue (MicroSeconds (1024*100)),
+ MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPperrMinInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "Dot11MeshHWMPactiveRootTimeout",
+ "Lifetime of poractive routing information",
+ TimeValue (MicroSeconds (1024*5000)),
+ MakeTimeAccessor (
+ &HwmpProtocol::m_dot11MeshHWMPactiveRootTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "Dot11MeshHWMPactivePathTimeout",
+ "Lifetime of reactive routing information",
+ TimeValue (MicroSeconds (1024*5000)),
+ MakeTimeAccessor (
+ &HwmpProtocol::m_dot11MeshHWMPactivePathTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "Dot11MeshHWMPpathToRootInterval",
+ "Interval between two successive proactive PREQs",
+ TimeValue (MicroSeconds (1024*2000)),
+ MakeTimeAccessor (
+ &HwmpProtocol::m_dot11MeshHWMPpathToRootInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "Dot11MeshHWMPrannInterval",
+ "Lifetime of poractive routing information",
+ TimeValue (MicroSeconds (1024*5000)),
+ MakeTimeAccessor (
+ &HwmpProtocol::m_dot11MeshHWMPrannInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "MaxTtl",
+ "Initial value of Time To Live field",
+ UintegerValue (32),
+ MakeUintegerAccessor (
+ &HwmpProtocol::m_maxTtl),
+ MakeUintegerChecker<uint8_t> (2)
+ )
+ .AddAttribute ( "UnicastPerrThreshold",
+ "Maximum number of PERR receivers, when we send a PERR as a chain of unicasts",
+ UintegerValue (32),
+ MakeUintegerAccessor (
+ &HwmpProtocol::m_unicastPerrThreshold),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ( "UnicastPreqThreshold",
+ "Maximum number of PREQ receivers, when we send a PREQ as a chain of unicasts",
+ UintegerValue (1),
+ MakeUintegerAccessor (
+ &HwmpProtocol::m_unicastPreqThreshold),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ( "UnicastDataThreshold",
+ "Maximum number ofbroadcast receivers, when we send a broadcast as a chain of unicasts",
+ UintegerValue (1),
+ MakeUintegerAccessor (
+ &HwmpProtocol::m_unicastDataThreshold),
+ MakeUintegerChecker<uint8_t> (1)
+ )
+ .AddAttribute ( "DoFlag",
+ "Destination only HWMP flag",
+ BooleanValue (false),
+ MakeBooleanAccessor (
+ &HwmpProtocol::m_doFlag),
+ MakeBooleanChecker ()
+ )
+ .AddAttribute ( "RfFlag",
+ "Reply and forward flag",
+ BooleanValue (true),
+ MakeBooleanAccessor (
+ &HwmpProtocol::m_rfFlag),
+ MakeBooleanChecker ()
+ );
+ return tid;
+}
+
+HwmpProtocol::HwmpProtocol ():
+ m_dataSeqno (1),
+ m_hwmpSeqno (1),
+ m_preqId (0),
+ m_rtable (CreateObject<HwmpRtable> ()),
+ m_randomStart(Seconds (0.1)),
+ m_maxQueueSize (255),
+ m_dot11MeshHWMPmaxPREQretries (3),
+ m_dot11MeshHWMPnetDiameterTraversalTime (MicroSeconds (1024*100)),
+ m_dot11MeshHWMPpreqMinInterval (MicroSeconds (1024*100)),
+ m_dot11MeshHWMPperrMinInterval (MicroSeconds (1024*100)),
+ m_dot11MeshHWMPactiveRootTimeout (MicroSeconds (1024*5000)),
+ m_dot11MeshHWMPactivePathTimeout (MicroSeconds (1024*5000)),
+ m_dot11MeshHWMPpathToRootInterval (MicroSeconds (1024*2000)),
+ m_dot11MeshHWMPrannInterval (MicroSeconds (1024*5000)),
+ m_isRoot (false),
+ m_maxTtl (32),
+ m_unicastPerrThreshold (32),
+ m_unicastPreqThreshold (1),
+ m_unicastDataThreshold (1),
+ m_doFlag (false),
+ m_rfFlag (false)
+{
+
+ if (m_isRoot)
+ {
+ SetRoot ();
+ }
+}
+
+HwmpProtocol::~HwmpProtocol ()
+{
+}
+
+void
+HwmpProtocol::DoDispose ()
+{
+ for (std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.begin (); i != m_preqTimeouts.end (); i ++)
+ {
+ i->second.Cancel ();
+ }
+ m_proactivePreqTimer.Cancel();
+ m_preqTimeouts.clear ();
+ m_lastDataSeqno.clear ();
+ m_lastHwmpSeqno.clear ();
+ m_rqueue.clear ();
+ m_rtable = 0;
+}
+
+bool
+HwmpProtocol::RequestRoute (
+ uint32_t sourceIface,
+ const Mac48Address source,
+ const Mac48Address destination,
+ Ptr<const Packet> constPacket,
+ uint16_t protocolType, //ethrnet 'Protocol' field
+ MeshL2RoutingProtocol::RouteReplyCallback routeReply
+)
+{
+ Ptr <Packet> packet = constPacket->Copy ();
+ HwmpTag tag;
+ if (sourceIface == GetMeshPoint ()->GetIfIndex())
+ {
+ // packet from level 3
+ if (packet->PeekPacketTag (tag))
+ {
+ NS_FATAL_ERROR ("HWMP tag has come with a packet from upper layer. This must not occur...");
+ }
+ //Filling TAG:
+ if (destination == Mac48Address::GetBroadcast ())
+ {
+ tag.SetSeqno (m_dataSeqno++);
+ }
+ tag.SetTtl (m_maxTtl);
+ }
+ else
+ {
+ if (!packet->RemovePacketTag (tag))
+ {
+ NS_FATAL_ERROR ("HWMP tag is supposed to be here at this point.");
+ }
+ tag.DecrementTtl ();
+ if (tag.GetTtl () == 0)
+ {
+ m_stats.droppedTtl ++;
+ return false;
+ }
+ }
+ if (destination == Mac48Address::GetBroadcast ())
+ {
+ m_stats.txBroadcast ++;
+ m_stats.txBytes += packet->GetSize ();
+ //channel IDs where we have already sent broadcast:
+ std::vector<uint16_t> channels;
+ for (HwmpProtocolMacMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin ++)
+ {
+ bool should_send = true;
+ for (std::vector<uint16_t>::const_iterator chan = channels.begin (); chan != channels.end (); chan ++)
+ {
+ if ((*chan) == plugin->second->GetChannelId ())
+ {
+ should_send = false;
+ }
+ }
+ if (!should_send)
+ {
+ continue;
+ }
+ channels.push_back (plugin->second->GetChannelId ());
+ std::vector<Mac48Address> receivers = GetBroadcastReceivers (plugin->first);
+ for (std::vector<Mac48Address>::const_iterator i = receivers.begin (); i != receivers.end (); i ++)
+ {
+ Ptr<Packet> packet_copy = packet->Copy();
+ tag.SetAddress (*i);
+ packet_copy->AddPacketTag (tag);
+ routeReply (true, packet_copy, source, destination, protocolType, plugin->first);
+ }
+ }
+ }
+ else
+ {
+ return ForwardUnicast (sourceIface, source, destination, packet, protocolType, routeReply, tag.GetTtl ());
+ }
+ return true;
+}
+bool
+HwmpProtocol::RemoveRoutingStuff (uint32_t fromIface, const Mac48Address source,
+ const Mac48Address destination, Ptr<Packet> packet, uint16_t& protocolType)
+{
+ HwmpTag tag;
+ if (!packet->RemovePacketTag (tag))
+ {
+ NS_FATAL_ERROR ("HWMP tag must exist when packet received from the network");
+ }
+ return true;
+}
+bool
+HwmpProtocol::ForwardUnicast (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply, uint32_t ttl)
+{
+ NS_ASSERT(destination != Mac48Address::GetBroadcast ());
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive (destination);
+ NS_LOG_DEBUG("Requested src = "<<source<<", dst = "<<destination<<", I am "<<GetAddress ()<<", RA = "<<result.retransmitter);
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ {
+ result = m_rtable->LookupProactive ();
+ }
+ HwmpTag tag;
+ tag.SetAddress (result.retransmitter);
+ tag.SetTtl (ttl);
+ //seqno and metric is not used;
+ packet->AddPacketTag (tag);
+ if (result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ //reply immediately:
+ routeReply (true, packet, source, destination, protocolType, result.ifIndex);
+ m_stats.txUnicast ++;
+ m_stats.txBytes += packet->GetSize ();
+ return true;
+ }
+ if (sourceIface != GetMeshPoint ()->GetIfIndex ())
+ {
+ //Start path error procedure:
+ NS_LOG_DEBUG ("Must Send PERR");
+ result = m_rtable->LookupReactiveExpired (destination);
+ //1. Lookup expired reactive path. If exists - start path error
+ // procedure towards a next hop of this path
+ //2. If there was no reactive path, we lookup expired proactive
+ // path. If exist - start path error procedure towards path to
+ // root
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ {
+ result = m_rtable->LookupProactiveExpired ();
+ }
+ if (result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ std::vector<IePerr::FailedDestination> destinations = m_rtable->GetUnreachableDestinations (result.retransmitter);
+ InitiatePathError (MakePathError (destinations));
+ }
+ m_stats.totalDropped ++;
+ return false;
+ }
+ //Request a destination:
+ result = m_rtable->LookupReactiveExpired (destination);
+ if (ShouldSendPreq (destination))
+ {
+ uint32_t originator_seqno = GetNextHwmpSeqno ();
+ uint32_t dst_seqno = 0;
+ if (result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ dst_seqno = result.seqnum;
+ }
+ m_stats.initiatedPreq ++;
+ for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ {
+ i->second->RequestDestination (destination, originator_seqno, dst_seqno);
+ }
+ }
+ QueuedPacket pkt;
+ pkt.pkt = packet;
+ pkt.dst = destination;
+ pkt.src = source;
+ pkt.protocol = protocolType;
+ pkt.reply = routeReply;
+ pkt.inInterface = sourceIface;
+ if (QueuePacket (pkt))
+ {
+ m_stats.totalQueued ++;
+ return true;
+ }
+ else
+ {
+ m_stats.totalDropped ++;
+ return false;
+ }
+}
+void
+HwmpProtocol::ReceivePreq (IePreq preq, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric)
+{
+ preq.IncrementMetric (metric);
+ //acceptance cretirea:
+ std::map<Mac48Address, uint32_t>::const_iterator i = m_lastHwmpSeqno.find (preq.GetOriginatorAddress());
+ if (i == m_lastHwmpSeqno.end ())
+ {
+ m_lastHwmpSeqno[preq.GetOriginatorAddress ()] = preq.GetOriginatorSeqNumber ();
+ m_lastHwmpMetric[preq.GetOriginatorAddress ()] = preq.GetMetric ();
+ }
+ else
+ {
+ if ((int32_t)(i->second - preq.GetOriginatorSeqNumber ()) > 0)
+ {
+ return;
+ }
+ if (i->second == preq.GetOriginatorSeqNumber ())
+ {
+ //find metric
+ std::map<Mac48Address, uint32_t>::const_iterator j = m_lastHwmpMetric.find (preq.GetOriginatorAddress());
+ NS_ASSERT (j != m_lastHwmpSeqno.end ());
+ if (j->second <= preq.GetMetric ())
+ {
+ return;
+ }
+ }
+ m_lastHwmpSeqno[preq.GetOriginatorAddress ()] = preq.GetOriginatorSeqNumber ();
+ m_lastHwmpMetric[preq.GetOriginatorAddress ()] = preq.GetMetric ();
+ }
+ NS_LOG_DEBUG("I am " << GetAddress () << "Accepted preq from address" << from << ", preq:" << preq);
+ std::vector<Ptr<DestinationAddressUnit> > destinations = preq.GetDestinationList ();
+ //Add reactive path to originator:
+ if (
+ ((m_rtable->LookupReactive (preq.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive (preq.GetOriginatorAddress ())).metric > preq.GetMetric ())
+ )
+ {
+ m_rtable->AddReactivePath (
+ preq.GetOriginatorAddress (),
+ from,
+ interface,
+ preq.GetMetric (),
+ MicroSeconds (preq.GetLifetime () * 1024),
+ preq.GetOriginatorSeqNumber ()
+ );
+ ReactivePathResolved (preq.GetOriginatorAddress ());
+ }
+ //Add reactive path for precursor:
+ if (
+ ((m_rtable->LookupReactive (fromMp)).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive (fromMp)).metric > preq.GetMetric ())
+ )
+ {
+ m_rtable->AddReactivePath (
+ fromMp,
+ from,
+ interface,
+ metric,
+ MicroSeconds (preq.GetLifetime () * 1024),
+ preq.GetOriginatorSeqNumber ()
+ );
+ ReactivePathResolved (fromMp);
+ }
+ for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator i = destinations.begin (); i != destinations.end (); i++)
+ {
+ if ((*i)->GetDestinationAddress () == Mac48Address::GetBroadcast())
+ {
+ //only proactive PREQ contains destination
+ //address as broadcast! Proactive preq MUST
+ //have destination count equal to 1 and
+ //per destination flags DO and RF
+ NS_ASSERT (preq.GetDestCount() == 1);
+ NS_ASSERT (((*i)->IsDo ()) && ((*i)->IsRf ()));
+ //Add proactive path only if it is the better then existed
+ //before
+ if (
+ ((m_rtable->LookupProactive ()).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupProactive ()).metric > preq.GetMetric ())
+ )
+ {
+ m_rtable->AddProactivePath (
+ preq.GetMetric (),
+ preq.GetOriginatorAddress (),
+ from,
+ interface,
+ MicroSeconds (preq.GetLifetime () * 1024),
+ preq.GetOriginatorSeqNumber ()
+ );
+ ProactivePathResolved ();
+ }
+ if (!preq.IsNeedNotPrep ())
+ {
+ SendPrep (
+ GetAddress (),
+ preq.GetOriginatorAddress (),
+ from,
+ preq.GetMetric (),
+ preq.GetOriginatorSeqNumber (),
+ GetNextHwmpSeqno (),
+ preq.GetLifetime (),
+ interface
+ );
+ }
+ break;
+ }
+ if ((*i)->GetDestinationAddress () == GetAddress ())
+ {
+ SendPrep (
+ GetAddress (),
+ preq.GetOriginatorAddress (),
+ from,
+ (uint32_t)0,
+ preq.GetOriginatorSeqNumber (),
+ GetNextHwmpSeqno (),
+ preq.GetLifetime (),
+ interface
+ );
+ NS_ASSERT(m_rtable->LookupReactive (preq.GetOriginatorAddress ()).retransmitter != Mac48Address::GetBroadcast ());
+ preq.DelDestinationAddressElement ((*i)->GetDestinationAddress ());
+ continue;
+ }
+ //check if can answer:
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive ((*i)->GetDestinationAddress ());
+ if ((! ((*i)->IsDo ())) && (result.retransmitter != Mac48Address::GetBroadcast ()))
+ {
+ //have a valid information and can answer
+ //!NB: If there is information from peer - set lifetime as
+ //we have got from PREQ, and set the rest lifetime of the
+ //route if the information is correct
+ uint32_t lifetime = result.lifetime.GetMicroSeconds () / 1024;
+ if ((lifetime > 0) && ((int32_t)(result.seqnum - (*i)->GetDestSeqNumber ()) >= 0))
+ {
+ SendPrep (
+ (*i)->GetDestinationAddress (),
+ preq.GetOriginatorAddress (),
+ from,
+ result.metric,
+ preq.GetOriginatorSeqNumber (),
+ result.seqnum,
+ lifetime,
+ interface
+ );
+ if ((*i)->IsRf ())
+ {
+ (*i)->SetFlags (true, false, (*i)->IsUsn ()); //DO = 1, RF = 0
+ }
+ else
+ {
+ preq.DelDestinationAddressElement ((*i)->GetDestinationAddress ());
+ continue;
+ }
+ }
+ }
+ }
+ //check if must retransmit:
+ if (preq.GetDestCount () == 0)
+ {
+ return;
+ }
+ //Forward PREQ to all interfaces:
+ NS_LOG_DEBUG("I am " << GetAddress () << "retransmitting PREQ:" << preq);
+ for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ {
+ i->second->SendPreq (preq);
+ }
+}
+void
+HwmpProtocol::ReceivePrep (IePrep prep, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric)
+{
+ prep.IncrementMetric (metric);
+ //acceptance cretirea:
+ std::map<Mac48Address, uint32_t>::const_iterator i = m_lastHwmpSeqno.find (prep.GetOriginatorAddress ());
+ if (i == m_lastHwmpSeqno.end ())
+ {
+ m_lastHwmpSeqno[prep.GetOriginatorAddress ()] = prep.GetOriginatorSeqNumber ();
+ }
+ else
+ {
+ if ((int32_t)(i->second - prep.GetOriginatorSeqNumber ()) > 0)
+ {
+ return;
+ }
+ else
+ {
+ m_lastHwmpSeqno[prep.GetOriginatorAddress ()] = prep.GetOriginatorSeqNumber ();
+ }
+ }
+ //update routing info
+ //Now add a path to destination and add precursor to source
+ NS_LOG_DEBUG("I am " << GetAddress () << ", received prep from " << prep.GetOriginatorAddress () << ", receiver was:" << from);
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive (prep.GetDestinationAddress ());
+ //Add a reactive path only if it is better than existing:
+ if (
+ ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive (prep.GetOriginatorAddress ())).metric > prep.GetMetric ())
+ )
+ {
+ m_rtable->AddReactivePath (
+ prep.GetOriginatorAddress (),
+ from,
+ interface,
+ prep.GetMetric (),
+ MicroSeconds(prep.GetLifetime () * 1024),
+ prep.GetOriginatorSeqNumber ());
+ m_rtable->AddPrecursor (prep.GetDestinationAddress (), interface, from);
+ if (result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ m_rtable->AddPrecursor (prep.GetOriginatorAddress (), interface, result.retransmitter);
+ }
+ ReactivePathResolved (prep.GetOriginatorAddress ());
+ }
+ if (
+ ((m_rtable->LookupReactive (fromMp)).retransmitter == Mac48Address::GetBroadcast ()) ||
+ ((m_rtable->LookupReactive (fromMp)).metric > prep.GetMetric ())
+ )
+ {
+ m_rtable->AddReactivePath (
+ fromMp,
+ from,
+ interface,
+ metric,
+ MicroSeconds(prep.GetLifetime () * 1024),
+ prep.GetOriginatorSeqNumber ());
+ ReactivePathResolved (fromMp);
+ }
+ if (prep.GetDestinationAddress () == GetAddress ())
+ {
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<", resolved "<<prep.GetOriginatorAddress ());
+ return;
+ }
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ {
+ //try to look for default route
+ result = m_rtable->LookupProactive ();
+ }
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ {
+ return;
+ }
+ //Forward PREP
+ HwmpProtocolMacMap::const_iterator prep_sender = m_interfaces.find (result.ifIndex);
+ NS_ASSERT (prep_sender != m_interfaces.end ());
+ prep_sender->second->SendPrep (prep, result.retransmitter);
+}
+void
+HwmpProtocol::ReceivePerr (std::vector<IePerr::FailedDestination> destinations, Mac48Address from, uint32_t interface, Mac48Address fromMp)
+{
+ //Acceptance cretirea:
+ NS_LOG_DEBUG("I am "<<GetAddress ()<<", received PERR from "<<from);
+ std::vector<IePerr::FailedDestination> retval;
+ HwmpRtable::LookupResult result;
+ for (unsigned int i = 0; i < destinations.size (); i ++)
+ {
+ result = m_rtable->LookupReactive (destinations[i].destination);
+ if (!(
+ (result.retransmitter != from) ||
+ (result.ifIndex != interface) ||
+ ((int32_t)(result.seqnum - destinations[i].seqnum) > 0)
+ ))
+ {
+ retval.push_back (destinations[i]);
+ }
+ }
+ if (retval.size () == 0)
+ {
+ return;
+ }
+ ForwardPathError (MakePathError (retval));
+}
+void
+HwmpProtocol::SendPrep (
+ Mac48Address src,
+ Mac48Address dst,
+ Mac48Address retransmitter,
+ uint32_t initMetric,
+ uint32_t originatorDsn,
+ uint32_t destinationSN,
+ uint32_t lifetime,
+ uint32_t interface)
+{
+ IePrep prep;
+ prep.SetHopcount (0);
+ prep.SetTtl (m_maxTtl);
+ prep.SetDestinationAddress (dst);
+ prep.SetDestinationSeqNumber (destinationSN);
+ prep.SetLifetime (lifetime);
+ prep.SetMetric (0);
+ prep.SetOriginatorAddress (src);
+ prep.SetOriginatorSeqNumber (originatorDsn);
+ HwmpProtocolMacMap::const_iterator prep_sender = m_interfaces.find (interface);
+ NS_ASSERT(prep_sender != m_interfaces.end ());
+ prep_sender->second->SendPrep (prep, retransmitter);
+ m_stats.initiatedPrep ++;
+}
+bool
+HwmpProtocol::Install (Ptr<MeshPointDevice> mp)
+{
+ m_mp = mp;
+ std::vector<Ptr<NetDevice> > interfaces = mp->GetInterfaces ();
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = interfaces.begin (); i != interfaces.end (); i++)
+ {
+ // Checking for compatible net device
+ Ptr<WifiNetDevice> wifiNetDev = (*i)->GetObject<WifiNetDevice> ();
+ if (wifiNetDev == 0)
+ {
+ return false;
+ }
+ Ptr<MeshWifiInterfaceMac> mac = wifiNetDev->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ if (mac == 0)
+ {
+ return false;
+ }
+ // Installing plugins:
+ Ptr<HwmpProtocolMac> hwmpMac = Create<HwmpProtocolMac> (wifiNetDev->GetIfIndex (), this);
+ m_interfaces[wifiNetDev->GetIfIndex ()] = hwmpMac;
+ mac->InstallPlugin (hwmpMac);
+ //Installing airtime link metric:
+ Ptr<AirtimeLinkMetricCalculator> metric = CreateObject <AirtimeLinkMetricCalculator> ();
+ mac->SetLinkMetricCallback (MakeCallback (&AirtimeLinkMetricCalculator::CalculateMetric, metric));
+ }
+ mp->SetRoutingProtocol (this);
+ // Mesh point aggregates all installed protocols
+ mp->AggregateObject (this);
+ m_address = Mac48Address::ConvertFrom (mp->GetAddress ());// address;
+ return true;
+}
+void
+HwmpProtocol::PeerLinkStatus(Mac48Address meshPointAddress, Mac48Address peerAddress, uint32_t interface, bool status)
+{
+ if (status)
+ {
+ return;
+ }
+ std::vector<IePerr::FailedDestination> destinations = m_rtable->GetUnreachableDestinations (peerAddress);
+ InitiatePathError (MakePathError (destinations));
+}
+void
+HwmpProtocol::SetNeighboursCallback (Callback<std::vector<Mac48Address>, uint32_t> cb)
+{
+ m_neighboursCallback = cb;
+}
+bool
+HwmpProtocol::DropDataFrame (uint32_t seqno, Mac48Address source)
+{
+ if (source == GetAddress ())
+ {
+ return true;
+ }
+ std::map<Mac48Address, uint32_t,std::less<Mac48Address> >::const_iterator i = m_lastDataSeqno.find (source);
+ if (i == m_lastDataSeqno.end ())
+ {
+ m_lastDataSeqno[source] = seqno;
+ }
+ else
+ {
+ if ((int32_t)(i->second - seqno) >= 0)
+ {
+ return true;
+ }
+ m_lastDataSeqno[source] = seqno;
+ }
+ return false;
+}
+HwmpProtocol::PathError
+HwmpProtocol::MakePathError (std::vector<IePerr::FailedDestination> destinations)
+{
+ PathError retval;
+ //HwmpRtable increments a sequence number as written in 11B.9.7.2
+ retval.receivers = GetPerrReceivers (destinations);
+ if (retval.receivers.size () == 0)
+ {
+ return retval;
+ }
+ m_stats.initiatedPerr ++;
+ for (unsigned int i = 0; i < destinations.size (); i ++)
+ {
+ retval.destinations.push_back (destinations[i]);
+ m_rtable->DeleteReactivePath (destinations[i].destination);
+ }
+ return retval;
+}
+void
+HwmpProtocol::InitiatePathError(PathError perr)
+{
+ for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ {
+ std::vector<Mac48Address> receivers_for_interface;
+ for (unsigned int j = 0; j < perr.receivers.size (); j ++)
+ {
+ if (i->first == perr.receivers[j].first)
+ {
+ receivers_for_interface.push_back (perr.receivers[j].second);
+ }
+ }
+ i->second->InitiatePerr (perr.destinations, receivers_for_interface);
+ }
+}
+void
+HwmpProtocol::ForwardPathError(PathError perr)
+{
+ for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ {
+ std::vector<Mac48Address> receivers_for_interface;
+ for (unsigned int j = 0; j < perr.receivers.size (); j ++)
+ {
+ if (i->first == perr.receivers[j].first)
+ {
+ receivers_for_interface.push_back (perr.receivers[j].second);
+ }
+ }
+ i->second->ForwardPerr (perr.destinations, receivers_for_interface);
+ }
+}
+
+std::vector<std::pair<uint32_t, Mac48Address> >
+HwmpProtocol::GetPerrReceivers (std::vector<IePerr::FailedDestination> failedDest)
+{
+ HwmpRtable::PrecursorList retval;
+ for (unsigned int i = 0; i < failedDest.size (); i ++)
+ {
+ HwmpRtable::PrecursorList precursors = m_rtable->GetPrecursors (failedDest[i].destination);
+ m_rtable->DeleteReactivePath (failedDest[i].destination);
+ m_rtable->DeleteProactivePath (failedDest[i].destination);
+ for (unsigned int j = 0; j < precursors.size (); j ++)
+ {
+ retval.push_back (precursors[j]);
+ }
+ }
+ //Check if we have dublicates in retval and precursors:
+ for (unsigned int i = 0; i < retval.size (); i ++)
+ {
+ for (unsigned int j = i+1; j < retval.size (); j ++)
+ {
+ if (retval[i].second == retval[j].second)
+ {
+ retval.erase (retval.begin () + j);
+ }
+ }
+ }
+ return retval;
+}
+std::vector<Mac48Address>
+HwmpProtocol::GetPreqReceivers (uint32_t interface)
+{
+ std::vector<Mac48Address> retval;
+ if (!m_neighboursCallback.IsNull ())
+ {
+ retval = m_neighboursCallback (interface);
+ }
+ if ((retval.size () >= m_unicastPreqThreshold) || (retval.size () == 0))
+ {
+ retval.clear ();
+ retval.push_back (Mac48Address::GetBroadcast ());
+ }
+ return retval;
+}
+std::vector<Mac48Address>
+HwmpProtocol::GetBroadcastReceivers (uint32_t interface)
+{
+ std::vector<Mac48Address> retval;
+ if (!m_neighboursCallback.IsNull ())
+ {
+ retval = m_neighboursCallback (interface);
+ }
+ if ((retval.size () >= m_unicastDataThreshold) || (retval.size () == 0))
+ {
+ retval.clear ();
+ retval.push_back (Mac48Address::GetBroadcast ());
+ }
+ return retval;
+}
+
+bool
+HwmpProtocol::QueuePacket (QueuedPacket packet)
+{
+ if (m_rqueue.size () > m_maxQueueSize)
+ {
+ return false;
+ }
+ m_rqueue.push_back (packet);
+ return true;
+}
+
+HwmpProtocol::QueuedPacket
+HwmpProtocol::DequeueFirstPacketByDst (Mac48Address dst)
+{
+ QueuedPacket retval;
+ retval.pkt = 0;
+ for (std::vector<QueuedPacket>::iterator i = m_rqueue.begin (); i != m_rqueue.end (); i++)
+ {
+ if ((*i).dst == dst)
+ {
+ retval = (*i);
+ m_rqueue.erase (i);
+ break;
+ }
+ }
+ return retval;
+}
+
+HwmpProtocol::QueuedPacket
+HwmpProtocol::DequeueFirstPacket ()
+{
+ QueuedPacket retval;
+ retval.pkt = 0;
+ if (m_rqueue.size () != 0)
+ {
+ retval = m_rqueue[0];
+ m_rqueue.erase (m_rqueue.begin ());
+ }
+ return retval;
+}
+
+void
+HwmpProtocol::ReactivePathResolved (Mac48Address dst)
+{
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive (dst);
+ NS_ASSERT(result.retransmitter != Mac48Address::GetBroadcast ());
+ //Send all packets stored for this destination
+ QueuedPacket packet = DequeueFirstPacketByDst (dst);
+ while (packet.pkt != 0)
+ {
+ //set RA tag for retransmitter:
+ HwmpTag tag;
+ packet.pkt->RemovePacketTag (tag);
+ tag.SetAddress (result.retransmitter);
+ packet.pkt->AddPacketTag (tag);
+ m_stats.txUnicast ++;
+ m_stats.txBytes += packet.pkt->GetSize ();
+ packet.reply (true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
+
+ packet = DequeueFirstPacketByDst (dst);
+ }
+}
+void
+HwmpProtocol::ProactivePathResolved ()
+{
+ //send all packets to root
+ HwmpRtable::LookupResult result = m_rtable->LookupProactive ();
+ NS_ASSERT (result.retransmitter != Mac48Address::GetBroadcast ());
+ QueuedPacket packet = DequeueFirstPacket ();
+ while (packet.pkt != 0)
+ {
+ //set RA tag for retransmitter:
+ HwmpTag tag;
+ if (!packet.pkt->RemovePacketTag (tag))
+ {
+ NS_FATAL_ERROR ("HWMP tag must be present at this point");
+ }
+ tag.SetAddress (result.retransmitter);
+ packet.pkt->AddPacketTag (tag);
+ m_stats.txUnicast ++;
+ m_stats.txBytes += packet.pkt->GetSize ();
+ packet.reply (true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
+
+ packet = DequeueFirstPacket ();
+ }
+}
+
+bool
+HwmpProtocol::ShouldSendPreq (Mac48Address dst)
+{
+ std::map<Mac48Address, EventId>::const_iterator i = m_preqTimeouts.find (dst);
+ if (i == m_preqTimeouts.end ())
+ {
+ m_preqTimeouts[dst] = Simulator::Schedule (
+ m_dot11MeshHWMPnetDiameterTraversalTime * Scalar (2),
+ &HwmpProtocol::RetryPathDiscovery, this, dst, 1);
+ return true;
+ }
+ return false;
+}
+void
+HwmpProtocol::RetryPathDiscovery (Mac48Address dst, uint8_t numOfRetry)
+{
+ HwmpRtable::LookupResult result = m_rtable->LookupReactive (dst);
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ {
+ result = m_rtable->LookupProactive ();
+ }
+ if (result.retransmitter != Mac48Address::GetBroadcast ())
+ {
+ std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.find (dst);
+ NS_ASSERT (i != m_preqTimeouts.end ());
+ m_preqTimeouts.erase (i);
+ return;
+ }
+ numOfRetry++;
+ if (numOfRetry >= m_dot11MeshHWMPmaxPREQretries)
+ {
+ QueuedPacket packet = DequeueFirstPacketByDst (dst);
+ //purge queue and delete entry from retryDatabase
+ while (packet.pkt != 0)
+ {
+ m_stats.totalDropped ++;
+ packet.reply (false, packet.pkt, packet.src, packet.dst, packet.protocol, HwmpRtable::MAX_METRIC);
+ packet = DequeueFirstPacketByDst (dst);
+ }
+ std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.find (dst);
+ NS_ASSERT (i != m_preqTimeouts.end ());
+ m_preqTimeouts.erase (i);
+ return;
+ }
+ uint32_t originator_seqno = GetNextHwmpSeqno ();
+ uint32_t dst_seqno = m_rtable->LookupReactiveExpired (dst).seqnum;
+ for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ {
+ i->second->RequestDestination (dst, originator_seqno, dst_seqno);
+ }
+ m_preqTimeouts[dst] = Simulator::Schedule (
+ Scalar (2 * (numOfRetry + 1)) * m_dot11MeshHWMPnetDiameterTraversalTime,
+ &HwmpProtocol::RetryPathDiscovery, this, dst, numOfRetry);
+}
+//Proactive PREQ routines:
+void
+HwmpProtocol::SetRoot ()
+{
+ UniformVariable coefficient (0.0, m_randomStart.GetSeconds());
+ Time randomStart = Seconds (coefficient.GetValue ());
+ m_proactivePreqTimer = Simulator::Schedule (randomStart, &HwmpProtocol::SendProactivePreq, this);
+ NS_LOG_DEBUG ("ROOT IS: " << m_address);
+ SendProactivePreq ();
+ m_isRoot = true;
+}
+void
+HwmpProtocol::UnsetRoot ()
+{
+ m_proactivePreqTimer.Cancel ();
+}
+void
+HwmpProtocol::SendProactivePreq ()
+{
+ IePreq preq;
+ //By default: must answer
+ preq.SetHopcount (0);
+ preq.SetTTL (m_maxTtl);
+ preq.SetLifetime (m_dot11MeshHWMPactiveRootTimeout.GetMicroSeconds () /1024);
+ //\attention: do not forget to set originator address, sequence
+ //number and preq ID in HWMP-MAC plugin
+ preq.AddDestinationAddressElement (true, true, Mac48Address::GetBroadcast (), 0);
+ preq.SetOriginatorAddress (GetAddress ());
+ preq.SetPreqID (GetNextPreqId ());
+ preq.SetOriginatorSeqNumber (GetNextHwmpSeqno ());
+ for (HwmpProtocolMacMap::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+ {
+ i->second->SendPreq (preq);
+ }
+ m_proactivePreqTimer = Simulator::Schedule (m_dot11MeshHWMPpathToRootInterval, &HwmpProtocol::SendProactivePreq, this);
+}
+bool
+HwmpProtocol::GetDoFlag ()
+{
+ return m_doFlag;
+}
+bool
+HwmpProtocol::GetRfFlag ()
+{
+ return m_rfFlag;
+}
+Time
+HwmpProtocol::GetPreqMinInterval ()
+{
+ return m_dot11MeshHWMPpreqMinInterval;
+}
+Time
+HwmpProtocol::GetPerrMinInterval ()
+{
+ return m_dot11MeshHWMPperrMinInterval;
+}
+uint8_t
+HwmpProtocol::GetMaxTtl ()
+{
+ return m_maxTtl;
+}
+uint32_t
+HwmpProtocol::GetNextPreqId ()
+{
+ m_preqId ++;
+ return m_preqId;
+}
+uint32_t
+HwmpProtocol::GetNextHwmpSeqno ()
+{
+ m_hwmpSeqno ++;
+ return m_hwmpSeqno;
+}
+uint32_t
+HwmpProtocol::GetActivePathLifetime ()
+{
+ return m_dot11MeshHWMPactivePathTimeout.GetMicroSeconds () / 1024;
+}
+uint8_t
+HwmpProtocol::GetUnicastPerrThreshold ()
+{
+ return m_unicastPerrThreshold;
+}
+Mac48Address
+HwmpProtocol::GetAddress ()
+{
+ return m_address;
+}
+//Statistics:
+HwmpProtocol::Statistics::Statistics () :
+ txUnicast (0),
+ txBroadcast (0),
+ txBytes (0),
+ droppedTtl (0),
+ totalQueued (0),
+ totalDropped (0),
+ initiatedPreq (0),
+ initiatedPrep (0),
+ initiatedPerr (0)
+{}
+void HwmpProtocol::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "txUnicast=\"" << txUnicast << "\" "
+ "txBroadcast=\"" << txBroadcast << "\" "
+ "txBytes=\"" << txBytes << "\" "
+ "droppedTtl=\"" << droppedTtl << "\" "
+ "totalQueued=\"" << totalQueued << "\" "
+ "totalDropped=\"" << totalDropped << "\" "
+ "initiatedPreq=\"" << initiatedPreq << "\" "
+ "initiatedPrep=\"" << initiatedPrep << "\" "
+ "initiatedPerr=\"" << initiatedPerr << "\"" << std::endl;
+}
+void
+HwmpProtocol::Report (std::ostream & os) const
+{
+ os << "<Hwmp "
+ "address=\"" << m_address << "\"" << std::endl <<
+ "maxQueueSize=\"" << m_maxQueueSize << "\"" << std::endl <<
+ "Dot11MeshHWMPmaxPREQretries=\"" << (uint16_t)m_dot11MeshHWMPmaxPREQretries << "\"" << std::endl <<
+ "Dot11MeshHWMPnetDiameterTraversalTime=\"" << m_dot11MeshHWMPnetDiameterTraversalTime.GetSeconds () << "\"" << std::endl <<
+ "Dot11MeshHWMPpreqMinInterval=\"" << m_dot11MeshHWMPpreqMinInterval.GetSeconds () << "\"" << std::endl <<
+ "Dot11MeshHWMPperrMinInterval=\"" << m_dot11MeshHWMPperrMinInterval.GetSeconds () << "\"" << std::endl <<
+ "Dot11MeshHWMPactiveRootTimeout=\"" << m_dot11MeshHWMPactiveRootTimeout.GetSeconds () << "\"" << std::endl <<
+ "Dot11MeshHWMPactivePathTimeout=\"" << m_dot11MeshHWMPactivePathTimeout.GetSeconds () << "\"" << std::endl <<
+ "Dot11MeshHWMPpathToRootInterval=\"" << m_dot11MeshHWMPpathToRootInterval.GetSeconds () << "\"" << std::endl <<
+ "Dot11MeshHWMPrannInterval=\"" << m_dot11MeshHWMPrannInterval.GetSeconds () << "\"" << std::endl <<
+ "isRoot=\"" << m_isRoot << "\"" << std::endl <<
+ "maxTtl=\"" << (uint16_t)m_maxTtl << "\"" << std::endl <<
+ "unicastPerrThreshold=\"" << (uint16_t)m_unicastPerrThreshold << "\"" << std::endl <<
+ "unicastPreqThreshold=\"" << (uint16_t)m_unicastPreqThreshold << "\"" << std::endl <<
+ "unicastDataThreshold=\"" << (uint16_t)m_unicastDataThreshold << "\"" << std::endl <<
+ "doFlag=\"" << m_doFlag << "\"" << std::endl <<
+ "rfFlag=\"" << m_rfFlag << "\">" << std::endl;
+ m_stats.Print (os);
+ for (HwmpProtocolMacMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin ++)
+ {
+ plugin->second->Report (os);
+ }
+ os << "</Hwmp>" << std::endl;
+}
+void
+HwmpProtocol::ResetStats ()
+{
+ m_stats = Statistics::Statistics ();
+ for (HwmpProtocolMacMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin ++)
+ {
+ plugin->second->ResetStats ();
+ }
+}
+HwmpProtocol::QueuedPacket::QueuedPacket () :
+ pkt (0),
+ protocol (0),
+ inInterface (0)
+{}
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-protocol.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,268 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef HWMP_PROTOCOL_H
+#define HWMP_PROTOCOL_H
+
+#include "ns3/mesh-l2-routing-protocol.h"
+#include "ns3/nstime.h"
+#include "ns3/event-id.h"
+#include "ie-dot11s-perr.h"
+#include <vector>
+#include <map>
+
+namespace ns3 {
+class MeshPointDevice;
+class Packet;
+class Mac48Address;
+namespace dot11s {
+class HwmpProtocolMac;
+class HwmpRtable;
+class IePreq;
+class IePrep;
+/**
+ * \ingroup dot11s
+ *
+ * \brief Hybrid wireless mesh protocol -- a routing protocol of IEEE 802.11s draft.
+ */
+class HwmpProtocol : public MeshL2RoutingProtocol
+{
+public:
+ static TypeId GetTypeId ();
+ HwmpProtocol ();
+ ~HwmpProtocol ();
+ void DoDispose ();
+
+ /// Route request, inherited from MeshL2RoutingProtocol
+ bool RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<const Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply);
+ /// Cleanup packet from all tags
+ bool RemoveRoutingStuff (uint32_t fromIface, const Mac48Address source,
+ const Mac48Address destination, Ptr<Packet> packet, uint16_t& protocolType);
+ /**
+ * \brief Install HWMP on given mesh point.
+ *
+ * Installing protocol cause installing its interface MAC plugins.
+ *
+ * Also MP aggregates all installed protocols, HWMP protocol can be accessed
+ * via MeshPointDevice::GetObject<dot11s::HwmpProtocol>();
+ */
+ bool Install (Ptr<MeshPointDevice>);
+ void PeerLinkStatus (Mac48Address meshPontAddress, Mac48Address peerAddress, uint32_t interface,bool status);
+ ///\brief This callback is used to obtain active neighbours on a
+ //given interface
+ ///\param interface is the interface ID
+ void SetNeighboursCallback (Callback<std::vector<Mac48Address>, uint32_t> cb);
+ ///\name Proactive PREQ mechanism:
+ ///\{
+ void SetRoot ();
+ void UnsetRoot ();
+ ///\}
+ ///\brief Statistics:
+ void Report (std::ostream &) const;
+ void ResetStats ();
+private:
+ friend class HwmpProtocolMac;
+
+ /// Like RequestRoute, but for unicast packets
+ bool ForwardUnicast (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply, uint32_t ttl);
+
+ ///\name Interaction with HWMP MAC plugin
+ //\{
+ void ReceivePreq (IePreq preq, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric);
+ void ReceivePrep (IePrep prep, Mac48Address from, uint32_t interface, Mac48Address fromMp, uint32_t metric);
+ void ReceivePerr (std::vector<IePerr::FailedDestination>, Mac48Address from, uint32_t interface, Mac48Address fromMp);
+ void SendPrep (
+ Mac48Address src,
+ Mac48Address dst,
+ Mac48Address retransmitter,
+ uint32_t initMetric,
+ uint32_t originatorDsn,
+ uint32_t destinationSN,
+ uint32_t lifetime,
+ uint32_t interface);
+ /**
+ * \brief Structure of path error: IePerr and list of receivers:
+ * interfaces and MAC address
+ */
+ struct PathError
+ {
+ std::vector<IePerr::FailedDestination> destinations;
+ /// interface-address
+ std::vector<std::pair<uint32_t, Mac48Address> > receivers;
+ };
+ /**
+ * \brief forms a path error information element when list of destination fails on a given interface
+ * \attention removes all entries from routing table!
+ */
+ PathError MakePathError (std::vector<IePerr::FailedDestination> destinations);
+ ///\brief Forwards a received path error
+ void ForwardPathError (PathError perr);
+ ///\brief Pasess a selg-generated PERR to interface-plugin
+ void InitiatePathError (PathError perr);
+ /// \return list of addresses where a PERR should be sent to
+ std::vector<std::pair<uint32_t, Mac48Address> > GetPerrReceivers (std::vector<IePerr::FailedDestination> failedDest);
+
+ /// \return list of addresses where a PERR should be sent to
+ std::vector<Mac48Address> GetPreqReceivers (uint32_t interface);
+ /// \return list of addresses where a broadcast should be
+ //retransmitted
+ std::vector<Mac48Address> GetBroadcastReceivers (uint32_t interface);
+ /**
+ * \brief MAC-plugin asks wether the frame can be dropeed. Protocol automatically updates seqno.
+ *
+ * \return true if frame can be dropped
+ * \param uint32_t is the seqno
+ * \param Mac48Address is the mesh source addrress of the frame
+ */
+ bool DropDataFrame (uint32_t, Mac48Address);
+ //\}
+private:
+ /// Packet waiting its routing information
+ struct QueuedPacket {
+ Ptr<Packet> pkt; ///< the packet
+ Mac48Address src; ///< src address
+ Mac48Address dst; ///< dst address
+ uint16_t protocol; ///< protocol number
+ uint32_t inInterface; ///< incoming device interface ID. (if packet has come from upper layers, this is Mesh point ID)
+ RouteReplyCallback reply; ///< how to reply
+
+ QueuedPacket ();
+ };
+
+ ///\name Methods related to Queue/Dequeue procedures
+ ///\{
+ bool QueuePacket (QueuedPacket packet);
+ QueuedPacket DequeueFirstPacketByDst (Mac48Address dst);
+ QueuedPacket DequeueFirstPacket ();
+ void ReactivePathResolved (Mac48Address dst);
+ void ProactivePathResolved ();
+ ///\}
+ ///\name Methods responsible for path discovery retry procedure:
+ ///\{
+ /**
+ * \brief checks when the last path discovery procedure was started for a given destination.
+ *
+ * If the retry counter has not achieved the maximum level - preq should not be sent
+ */
+ bool ShouldSendPreq (Mac48Address dst);
+
+ /**
+ * \brief Generates PREQ retry when retry timeout has expired and route is still unresolved.
+ *
+ * When PREQ retry has achieved the maximum level - retry mechanish should be cancelled
+ */
+ void RetryPathDiscovery (Mac48Address dst, uint8_t numOfRetry);
+ ///\}
+
+ ///\name Proactive Preq routines:
+ ///\{
+ void SendProactivePreq ();
+ ///\}
+ ///\return address of MeshPointDevice
+ Mac48Address GetAddress ();
+private:
+ typedef std::map<uint32_t, Ptr<HwmpProtocolMac> > HwmpProtocolMacMap;
+ HwmpProtocolMacMap m_interfaces;
+ ///\name Statistics:
+ ///\{
+ struct Statistics
+ {
+ uint16_t txUnicast;
+ uint16_t txBroadcast;
+ uint32_t txBytes;
+ uint16_t droppedTtl;
+ uint16_t totalQueued;
+ uint16_t totalDropped;
+ uint16_t initiatedPreq;
+ uint16_t initiatedPrep;
+ uint16_t initiatedPerr;
+
+ void Print (std::ostream & os) const;
+ Statistics ();
+ };
+ Statistics m_stats;
+ ///\}
+ Mac48Address m_address;
+ uint32_t m_dataSeqno;
+ uint32_t m_hwmpSeqno;
+ uint32_t m_preqId;
+ ///\name Sequence number filters
+ ///\{
+ /// Data sequence number database
+ std::map<Mac48Address, uint32_t> m_lastDataSeqno;
+ /// DSN databse
+ std::map<Mac48Address, uint32_t> m_lastHwmpSeqno;
+ /// Metric database
+ std::map<Mac48Address, uint32_t> m_lastHwmpMetric;
+ ///\}
+
+ /// Routing table
+ Ptr<HwmpRtable> m_rtable;
+
+ ///\name Timers:
+ ///\{
+ std::map<Mac48Address, EventId> m_preqTimeouts;
+ EventId m_proactivePreqTimer;
+ //Random start in Proactive PREQ propagation
+ Time m_randomStart;
+ ///\}
+
+ /// Packet Queue
+ std::vector<QueuedPacket> m_rqueue;
+private:
+ ///\name HWMP-protocol parameters (attributes of GetTypeId)
+ ///\{
+ uint16_t m_maxQueueSize;
+ uint8_t m_dot11MeshHWMPmaxPREQretries;
+ Time m_dot11MeshHWMPnetDiameterTraversalTime;
+ Time m_dot11MeshHWMPpreqMinInterval;
+ Time m_dot11MeshHWMPperrMinInterval;
+ Time m_dot11MeshHWMPactiveRootTimeout;
+ Time m_dot11MeshHWMPactivePathTimeout;
+ Time m_dot11MeshHWMPpathToRootInterval;
+ Time m_dot11MeshHWMPrannInterval;
+ bool m_isRoot;
+ uint8_t m_maxTtl;
+ uint8_t m_unicastPerrThreshold;
+ uint8_t m_unicastPreqThreshold;
+ uint8_t m_unicastDataThreshold;
+ bool m_doFlag;
+ bool m_rfFlag;
+ ///\}
+
+ ///\name Methods needed by HwmpMacLugin to access protocol parameters:
+ ///\{
+ bool GetDoFlag ();
+ bool GetRfFlag ();
+ Time GetPreqMinInterval ();
+ Time GetPerrMinInterval ();
+ uint8_t GetMaxTtl ();
+ uint32_t GetNextPreqId ();
+ uint32_t GetNextHwmpSeqno ();
+ uint32_t GetActivePathLifetime ();
+ uint8_t GetUnicastPerrThreshold ();
+ ///\}
+ Callback <std::vector<Mac48Address>, uint32_t> m_neighboursCallback;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-rtable.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,393 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ns3/object.h"
+#include "ns3/assert.h"
+#include "ns3/simulator.h"
+#include "ns3/test.h"
+#include "ns3/log.h"
+
+#include "hwmp-rtable.h"
+
+namespace ns3 {
+namespace dot11s {
+
+NS_LOG_COMPONENT_DEFINE ("HwmpRtable");
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpRtable);
+
+TypeId
+HwmpRtable::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::HwmpRtable")
+ .SetParent<Object> ()
+ .AddConstructor<HwmpRtable> ();
+ return tid;
+}
+HwmpRtable::HwmpRtable ()
+{
+ DeleteProactivePath ();
+}
+HwmpRtable::~HwmpRtable ()
+{
+}
+void
+HwmpRtable::DoDispose ()
+{
+ m_routes.clear ();
+}
+void
+HwmpRtable::AddReactivePath (Mac48Address destination, Mac48Address retransmitter, uint32_t interface,
+ uint32_t metric, Time lifetime, uint32_t seqnum)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ {
+ ReactiveRoute newroute;
+ m_routes[destination] = newroute;
+ }
+ i = m_routes.find (destination);
+ NS_ASSERT (i != m_routes.end ());
+ i->second.retransmitter = retransmitter;
+ i->second.interface = interface;
+ i->second.metric = metric;
+ i->second.whenExpire = Simulator::Now () + lifetime;
+ i->second.seqnum = seqnum;
+}
+void
+HwmpRtable::AddProactivePath (uint32_t metric, Mac48Address root, Mac48Address retransmitter,
+ uint32_t interface, Time lifetime, uint32_t seqnum)
+{
+ m_root.root = root;
+ m_root.retransmitter = retransmitter;
+ m_root.metric = metric;
+ m_root.whenExpire = Simulator::Now () + lifetime;
+ m_root.seqnum = seqnum;
+ m_root.interface = interface;
+}
+void
+HwmpRtable::AddPrecursor (Mac48Address destination, uint32_t precursorInterface,
+ Mac48Address precursorAddress)
+{
+ std::pair<uint32_t, Mac48Address> precursor;
+ precursor.first = precursorInterface;
+ precursor.second = precursorAddress;
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i != m_routes.end ())
+ {
+ bool should_add = true;
+ for (unsigned int j = 0; j < i->second.precursors.size (); j++)
+ {
+ //NB: Only one active route may exist, so do not check
+ //interface ID, just address
+ if (i->second.precursors[j].second == precursorAddress)
+ {
+ should_add = false;
+ break;
+ }
+ }
+ if (should_add)
+ {
+ i->second.precursors.push_back (precursor);
+ }
+ }
+ if (m_root.root == destination)
+ {
+ for (unsigned int j = 0; j < m_root.precursors.size (); j++)
+ {
+ if (m_root.precursors[j].second == precursorAddress)
+ {
+ return;
+ }
+ }
+ }
+ m_root.precursors.push_back (precursor);
+}
+void
+HwmpRtable::DeleteProactivePath ()
+{
+ m_root.precursors.clear ();
+ m_root.interface = INTERFACE_ANY;
+ m_root.metric = MAX_METRIC;
+ m_root.retransmitter = Mac48Address::GetBroadcast ();
+ m_root.seqnum = 0;
+ m_root.whenExpire = Simulator::Now ();
+}
+void
+HwmpRtable::DeleteProactivePath (Mac48Address root)
+{
+ if (m_root.root == root)
+ {
+ DeleteProactivePath ();
+ }
+}
+void
+HwmpRtable::DeleteReactivePath (Mac48Address destination)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i != m_routes.end ())
+ {
+ m_routes.erase (i);
+ }
+}
+HwmpRtable::LookupResult
+HwmpRtable::LookupReactive (Mac48Address destination)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ {
+ return LookupResult ();
+ }
+ if ((i->second.whenExpire < Simulator::Now ()) && (i->second.whenExpire != Seconds (0)))
+ {
+ NS_LOG_DEBUG ("Reactive route has expired, sorry.");
+ return LookupResult ();
+ }
+ return LookupReactiveExpired (destination);
+}
+HwmpRtable::LookupResult
+HwmpRtable::LookupReactiveExpired (Mac48Address destination)
+{
+ std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ {
+ return LookupResult ();
+ }
+ return LookupResult (i->second.retransmitter, i->second.interface, i->second.metric, i->second.seqnum,
+ i->second.whenExpire - Simulator::Now ());
+}
+HwmpRtable::LookupResult
+HwmpRtable::LookupProactive ()
+{
+ if (m_root.whenExpire < Simulator::Now ())
+ {
+ NS_LOG_DEBUG ("Proactive route has expired and will be deleted, sorry.");
+ DeleteProactivePath ();
+ }
+ return LookupProactiveExpired ();
+}
+HwmpRtable::LookupResult
+HwmpRtable::LookupProactiveExpired ()
+{
+ return LookupResult (m_root.retransmitter, m_root.interface, m_root.metric, m_root.seqnum,
+ m_root.whenExpire - Simulator::Now ());
+}
+std::vector<IePerr::FailedDestination>
+HwmpRtable::GetUnreachableDestinations (Mac48Address peerAddress)
+{
+ IePerr::FailedDestination dst;
+ std::vector<IePerr::FailedDestination> retval;
+ for (std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.begin (); i != m_routes.end (); i++)
+ {
+ if (i->second.retransmitter == peerAddress)
+ {
+ dst.destination = i->first;
+ i->second.seqnum++;
+ dst.seqnum = i->second.seqnum;
+ retval.push_back (dst);
+ }
+ }
+ //Lookup a path to root
+ if (m_root.retransmitter == peerAddress)
+ {
+ dst.destination = m_root.root;
+ dst.seqnum = m_root.seqnum;
+ retval.push_back (dst);
+ }
+ return retval;
+}
+HwmpRtable::PrecursorList
+HwmpRtable::GetPrecursors (Mac48Address destination)
+{
+ //We suppose that no duplicates here can be
+ PrecursorList retval;
+ std::map<Mac48Address, ReactiveRoute>::iterator route = m_routes.find (destination);
+ if (route != m_routes.end ())
+ {
+ for (unsigned int i = 0; i < route->second.precursors.size (); i++)
+ {
+ retval.push_back (route->second.precursors[i]);
+ }
+ }
+ if (m_root.root == destination)
+ {
+ for (unsigned int i = 0; i < m_root.precursors.size (); i++)
+ {
+ bool should_add = true;
+ for (unsigned int j = 0; j < retval.size (); j++)
+ {
+ if (retval[j].second == m_root.precursors[i].second)
+ {
+ should_add = false;
+ break;
+ }
+ }
+ if (should_add)
+ {
+ retval.push_back (m_root.precursors[i]);
+ }
+ }
+ }
+ return retval;
+}
+bool
+HwmpRtable::LookupResult::operator== (const HwmpRtable::LookupResult & o) const
+{
+ return (retransmitter == o.retransmitter && ifIndex == o.ifIndex && metric == o.metric && seqnum
+ == o.seqnum);
+}
+HwmpRtable::LookupResult::LookupResult (Mac48Address r, uint32_t i, uint32_t m, uint32_t s, Time l) :
+ retransmitter (r), ifIndex (i), metric (m), seqnum (s), lifetime (l)
+{
+}
+bool
+HwmpRtable::LookupResult::IsValid () const
+{
+ return !(retransmitter == Mac48Address::GetBroadcast () && ifIndex == INTERFACE_ANY && metric == MAX_METRIC
+ && seqnum == 0);
+}
+#ifdef RUN_SELF_TESTS
+/// Unit test for HwmpRtable
+class HwmpRtableTest : public Test
+{
+public:
+ HwmpRtableTest ();
+ virtual bool
+ RunTests ();
+
+private:
+ /// Test Add apth and lookup path;
+ void
+ TestLookup ();
+ /**
+ * \name Test add path and try to lookup after entry has expired
+ * \{
+ */
+ void
+ TestAddPath ();
+ void
+ TestExpire ();
+ ///\}
+ /**
+ * \name Test add precursors and find precursor list in rtable
+ * \{
+ */
+ void
+ TestPrecursorAdd ();
+ void
+ TestPrecursorFind ();
+ ///\}
+private:
+ bool result;
+
+ Mac48Address dst;
+ Mac48Address hop;
+ uint32_t iface;
+ uint32_t metric;
+ uint32_t seqnum;
+ Time expire;
+ Ptr<HwmpRtable> table;
+ std::vector<Mac48Address> precursors;
+};
+/// Test instance
+static HwmpRtableTest g_HwmpRtableTest;
+
+HwmpRtableTest::HwmpRtableTest () :
+ Test ("Mesh/802.11s/HwmpRtable"), result (true), dst ("01:00:00:01:00:01"), hop ("01:00:00:01:00:03"),
+ iface (8010), metric (10), seqnum (1), expire (Seconds (10))
+{
+ precursors.push_back (Mac48Address ("00:10:20:30:40:50"));
+ precursors.push_back (Mac48Address ("00:11:22:33:44:55"));
+ precursors.push_back (Mac48Address ("00:01:02:03:04:05"));
+}
+void
+HwmpRtableTest::TestLookup ()
+{
+ HwmpRtable::LookupResult correct (hop, iface, metric, seqnum);
+
+ // Reactive path
+ table->AddReactivePath (dst, hop, iface, metric, expire, seqnum);
+ NS_TEST_ASSERT (table->LookupReactive (dst) == correct);
+ table->DeleteReactivePath (dst);
+ NS_TEST_ASSERT (!table->LookupReactive (dst).IsValid ());
+
+ // Proactive
+ table->AddProactivePath (metric, dst, hop, iface, expire, seqnum);
+ NS_TEST_ASSERT (table->LookupProactive () == correct);
+ table->DeleteProactivePath (dst);
+ NS_TEST_ASSERT (!table->LookupProactive ().IsValid ());
+}
+void
+HwmpRtableTest::TestAddPath ()
+{
+ table->AddReactivePath (dst, hop, iface, metric, expire, seqnum);
+ table->AddProactivePath (metric, dst, hop, iface, expire, seqnum);
+}
+void
+HwmpRtableTest::TestExpire ()
+{
+ // this is assumed to be called when path records are already expired
+ HwmpRtable::LookupResult correct (hop, iface, metric, seqnum);
+ NS_TEST_ASSERT (table->LookupReactiveExpired (dst) == correct);
+ NS_TEST_ASSERT (table->LookupProactiveExpired () == correct);
+
+ NS_TEST_ASSERT (!table->LookupReactive (dst).IsValid ());
+ NS_TEST_ASSERT (!table->LookupProactive ().IsValid ());
+}
+void
+HwmpRtableTest::TestPrecursorAdd ()
+{
+ for (std::vector<Mac48Address>::const_iterator i = precursors.begin (); i != precursors.end (); i++)
+ {
+ table->AddPrecursor (dst, iface, *i);
+ // Check that duplicates are filtered
+ table->AddPrecursor (dst, iface, *i);
+ }
+}
+void
+HwmpRtableTest::TestPrecursorFind ()
+{
+ HwmpRtable::PrecursorList precursorList = table->GetPrecursors (dst);
+ NS_TEST_ASSERT (precursors.size () == precursorList.size ());
+ for (unsigned int i = 0; i < precursors.size (); i++)
+ {
+ NS_TEST_ASSERT (precursorList[i].first == iface);
+ NS_TEST_ASSERT (precursorList[i].second == precursors[i]);
+ }
+}
+bool
+HwmpRtableTest::RunTests ()
+{
+ table = CreateObject<HwmpRtable> ();
+
+ Simulator::Schedule (Seconds (0), &HwmpRtableTest::TestLookup, this);
+ Simulator::Schedule (Seconds (1), &HwmpRtableTest::TestAddPath, this);
+ Simulator::Schedule (Seconds (2), &HwmpRtableTest::TestPrecursorAdd, this);
+ Simulator::Schedule (expire + Seconds (2), &HwmpRtableTest::TestExpire, this);
+ Simulator::Schedule (expire + Seconds (3), &HwmpRtableTest::TestPrecursorFind, this);
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return result;
+}
+#endif // RUN_SELF_TESTS
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-rtable.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef HWMP_RTABLE_H
+#define HWMP_RTABLE_H
+
+#include <map>
+#include "ns3/nstime.h"
+#include "ns3/mac48-address.h"
+#include "ie-dot11s-perr.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Routing table for HWMP -- 802.11s routing protocol
+ */
+class HwmpRtable : public Object
+{
+public:
+ /// Means all interfaces
+ const static uint32_t INTERFACE_ANY = 0xffffffff;
+ /// Maximum (the best?) path metric
+ const static uint32_t MAX_METRIC = 0xffffffff;
+
+ /// Route lookup result, return type of LookupXXX methods
+ struct LookupResult
+ {
+ Mac48Address retransmitter;
+ uint32_t ifIndex;
+ uint32_t metric;
+ uint32_t seqnum;
+ Time lifetime;
+ LookupResult (Mac48Address r = Mac48Address::GetBroadcast (),
+ uint32_t i = INTERFACE_ANY,
+ uint32_t m = MAX_METRIC,
+ uint32_t s = 0,
+ Time l = Seconds (0.0));
+ /// True for valid route
+ bool IsValid () const;
+ /// Compare route lookup results, used by tests
+ bool operator==(const LookupResult & o) const;
+ };
+ /// Path precursor = {MAC, interface ID}
+ typedef std::vector<std::pair<uint32_t, Mac48Address> > PrecursorList;
+
+public:
+ static TypeId GetTypeId ();
+ HwmpRtable ();
+ ~HwmpRtable ();
+ void DoDispose ();
+
+ ///\name Add/delete paths
+ //\{
+ void AddReactivePath (
+ Mac48Address destination,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ uint32_t metric,
+ Time lifetime,
+ uint32_t seqnum
+ );
+ void AddProactivePath (
+ uint32_t metric,
+ Mac48Address root,
+ Mac48Address retransmitter,
+ uint32_t interface,
+ Time lifetime,
+ uint32_t seqnum
+ );
+ void AddPrecursor (Mac48Address destination, uint32_t precursorInterface, Mac48Address precursorAddress);
+ PrecursorList GetPrecursors (Mac48Address destination);
+ void DeleteProactivePath ();
+ void DeleteProactivePath (Mac48Address root);
+ void DeleteReactivePath (Mac48Address destination);
+ //\}
+
+ ///\name Lookup
+ //\{
+ /// Lookup path to destination
+ LookupResult LookupReactive (Mac48Address destination);
+ /// Return all reactive paths, including expired
+ LookupResult LookupReactiveExpired (Mac48Address destination);
+ /// Find proactive path to tree root. Note that calling this method has side effect of deleting expired proactive path
+ LookupResult LookupProactive ();
+ /// Return all proactive paths, including expired
+ LookupResult LookupProactiveExpired ();
+ //\}
+
+ /// When peer link with a given MAC-address fails - it returns list of unreachable destination addresses
+ std::vector<IePerr::FailedDestination> GetUnreachableDestinations (Mac48Address peerAddress);
+
+private:
+ /// Route found in reactive mode
+ struct ReactiveRoute
+ {
+ Mac48Address retransmitter;
+ uint32_t interface;
+ uint32_t metric;
+ Time whenExpire;
+ uint32_t seqnum;
+ std::vector<std::pair<uint32_t, Mac48Address> > precursors;
+ };
+ /// Route fond in proactive mode
+ struct ProactiveRoute
+ {
+ Mac48Address root;
+ Mac48Address retransmitter;
+ uint32_t interface;
+ uint32_t metric;
+ Time whenExpire;
+ uint32_t seqnum;
+ std::vector<std::pair<uint32_t, Mac48Address> > precursors;
+ };
+
+ /// List of routes
+ std::map<Mac48Address, ReactiveRoute> m_routes;
+ /// Path to proactive tree root MP
+ ProactiveRoute m_root;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-tag.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "hwmp-tag.h"
+
+namespace ns3 {
+namespace dot11s {
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpTag);
+//Class HwmpTag:
+HwmpTag::HwmpTag () :
+ m_address (Mac48Address::GetBroadcast ()), m_ttl (0), m_metric (0), m_seqno (0)
+{
+}
+
+HwmpTag::~HwmpTag ()
+{
+}
+
+void
+HwmpTag::SetAddress (Mac48Address retransmitter)
+{
+ m_address = retransmitter;
+}
+
+Mac48Address
+HwmpTag::GetAddress ()
+{
+ return m_address;
+}
+
+void
+HwmpTag::SetTtl (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+
+uint8_t
+HwmpTag::GetTtl ()
+{
+ return m_ttl;
+}
+
+void
+HwmpTag::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+
+uint32_t
+HwmpTag::GetMetric ()
+{
+ return m_metric;
+}
+
+void
+HwmpTag::SetSeqno (uint32_t seqno)
+{
+ m_seqno = seqno;
+}
+
+uint32_t
+HwmpTag::GetSeqno ()
+{
+ return m_seqno;
+}
+
+TypeId
+HwmpTag::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::HwmpTag") .SetParent<Tag> () .AddConstructor<HwmpTag> ();
+ return tid;
+}
+
+TypeId
+HwmpTag::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+
+uint32_t
+HwmpTag::GetSerializedSize () const
+{
+ return 6 //address
+ + 1 //ttl
+ + 4 //metric
+ + 4; //seqno
+}
+
+void
+HwmpTag::Serialize (TagBuffer i) const
+{
+ uint8_t address[6];
+ int j;
+ m_address.CopyTo (address);
+ i.WriteU8 (m_ttl);
+ i.WriteU32 (m_metric);
+ i.WriteU32 (m_seqno);
+ for (j = 0; j < 6; j++)
+ {
+ i.WriteU8 (address[j]);
+ }
+}
+
+void
+HwmpTag::Deserialize (TagBuffer i)
+{
+ uint8_t address[6];
+ int j;
+ m_ttl = i.ReadU8 ();
+ m_metric = i.ReadU32 ();
+ m_seqno = i.ReadU32 ();
+ for (j = 0; j < 6; j++)
+ {
+ address[j] = i.ReadU8 ();
+ }
+ m_address.CopyFrom (address);
+}
+
+void
+HwmpTag::Print (std::ostream &os) const
+{
+ os << "address=" << m_address;
+ os << "ttl=" << m_ttl;
+ os << "metrc=" << m_metric;
+ os << "seqno=" << m_seqno;
+}
+void
+HwmpTag::DecrementTtl ()
+{
+ m_ttl--;
+}
+} //namespace dot11s
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/hwmp-tag.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef HWMP_TAG_H
+#define HWMP_TAG_H
+
+#include "ns3/tag.h"
+#include "ns3/object.h"
+#include "ns3/mac48-address.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Hwmp tag implements interaction between HWMP
+ * protocol and MeshWifiMac
+ *
+ * \details Hwmp tag keeps the following:
+ * 1. When packet is passed from Hwmp to 11sMAC:
+ * - retransmitter address,
+ * - TTL value,
+ * 2. When packet is passed to Hwmp from 11sMAC:
+ * - lasthop address,
+ * - TTL value,
+ * - metric value (metric of link is recalculated
+ * at each packet, but routing table stores metric
+ * obtained during path discovery procedure)
+ */
+class HwmpTag : public Tag
+{
+public:
+ HwmpTag ();
+ ~HwmpTag ();
+ void SetAddress (Mac48Address retransmitter);
+ Mac48Address GetAddress ();
+ void SetTtl (uint8_t ttl);
+ uint8_t GetTtl ();
+ void SetMetric (uint32_t metric);
+ uint32_t GetMetric ();
+ void SetSeqno (uint32_t seqno);
+ uint32_t GetSeqno ();
+ void DecrementTtl ();
+
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (TagBuffer i) const;
+ virtual void Deserialize (TagBuffer i);
+ virtual void Print (std::ostream &os) const;
+private:
+ Mac48Address m_address;
+ uint8_t m_ttl;
+ uint32_t m_metric;
+ uint32_t m_seqno;
+};
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-beacon-timing.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,225 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-beacon-timing.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+/*******************************************
+ * IeBeaconTimingUnit
+ *******************************************/
+IeBeaconTimingUnit::IeBeaconTimingUnit () :
+ m_aid (0), m_lastBeacon (0), m_beaconInterval (0)
+{
+}
+void
+IeBeaconTimingUnit::SetAid (uint8_t aid)
+{
+ m_aid = aid;
+}
+void
+IeBeaconTimingUnit::SetLastBeacon (uint16_t lastBeacon)
+{
+ m_lastBeacon = lastBeacon;
+}
+void
+IeBeaconTimingUnit::SetBeaconInterval (uint16_t beaconInterval)
+{
+ m_beaconInterval = beaconInterval;
+}
+uint8_t
+IeBeaconTimingUnit::GetAid () const
+{
+ return m_aid;
+}
+uint16_t
+IeBeaconTimingUnit::GetLastBeacon () const
+{
+ return m_lastBeacon;
+}
+uint16_t
+IeBeaconTimingUnit::GetBeaconInterval () const
+{
+ return m_beaconInterval;
+}
+/*******************************************
+ * IeBeaconTiming
+ *******************************************/
+WifiElementId
+IeBeaconTiming::ElementId () const
+{
+ return IE11S_BEACON_TIMING;
+}
+IeBeaconTiming::IeBeaconTiming () :
+ m_numOfUnits (0)
+{
+}
+IeBeaconTiming::NeighboursTimingUnitsList
+IeBeaconTiming::GetNeighboursTimingElementsList ()
+{
+ return m_neighbours;
+}
+void
+IeBeaconTiming::AddNeighboursTimingElementUnit (uint16_t aid, Time last_beacon, //MicroSeconds!
+ Time beacon_interval //MicroSeconds!
+)
+{
+ if (m_numOfUnits == 50)
+ {
+ return;
+ }
+ //First we lookup if this element already exists
+ for (NeighboursTimingUnitsList::const_iterator i = m_neighbours.begin (); i != m_neighbours.end (); i++)
+ {
+ if (((*i)->GetAid () == AidToU8 (aid)) && ((*i)->GetLastBeacon () == TimestampToU16 (last_beacon))
+ && ((*i)->GetBeaconInterval () == BeaconIntervalToU16 (beacon_interval)))
+ {
+ return;
+ }
+ }
+ Ptr<IeBeaconTimingUnit> new_element = Create<IeBeaconTimingUnit> ();
+ new_element->SetAid (AidToU8 (aid));
+ new_element->SetLastBeacon (TimestampToU16 (last_beacon));
+ new_element->SetBeaconInterval (BeaconIntervalToU16 (beacon_interval));
+ m_neighbours.push_back (new_element);
+ m_numOfUnits++;
+}
+void
+IeBeaconTiming::DelNeighboursTimingElementUnit (uint16_t aid, Time last_beacon, Time beacon_interval)
+{
+ for (NeighboursTimingUnitsList::iterator i = m_neighbours.begin (); i != m_neighbours.end (); i++)
+ {
+ if (((*i)->GetAid () == AidToU8 (aid)) && ((*i)->GetLastBeacon () == TimestampToU16 (last_beacon))
+ && ((*i)->GetBeaconInterval () == BeaconIntervalToU16 (beacon_interval)))
+ {
+ m_neighbours.erase (i);
+ m_numOfUnits--;
+ break;
+ }
+ }
+}
+void
+IeBeaconTiming::ClearTimingElement ()
+{
+ uint16_t to_delete = 0;
+ uint16_t i;
+ for (NeighboursTimingUnitsList::iterator j = m_neighbours.begin (); j != m_neighbours.end (); j++)
+ {
+ to_delete++;
+ (*j) = 0;
+ }
+ for (i = 0; i < to_delete; i++)
+ {
+ m_neighbours.pop_back ();
+ }
+ m_neighbours.clear ();
+
+}
+uint8_t
+IeBeaconTiming::GetInformationSize () const
+{
+ return (5 * m_numOfUnits );
+}
+void
+IeBeaconTiming::Print (std::ostream& os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << "Number of units: " << (uint16_t) m_numOfUnits << std::endl;
+ for (NeighboursTimingUnitsList::const_iterator j = m_neighbours.begin (); j != m_neighbours.end (); j++)
+ {
+ os << "AID=" << (uint16_t) (*j)->GetAid () << ", Last beacon was at " << (*j)->GetLastBeacon ()
+ << ", with beacon interval " << (*j)->GetBeaconInterval () << std::endl;
+ }
+ os << "</information_element>" << std::endl;
+}
+void
+IeBeaconTiming::SerializeInformation (Buffer::Iterator i) const
+{
+ for (NeighboursTimingUnitsList::const_iterator j = m_neighbours.begin (); j != m_neighbours.end (); j++)
+ {
+ i.WriteU8 ((*j)->GetAid ());
+ i.WriteHtolsbU16 ((*j)->GetLastBeacon ());
+ i.WriteHtolsbU16 ((*j)->GetBeaconInterval ());
+ }
+}
+uint8_t
+IeBeaconTiming::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_numOfUnits = length / 5;
+ for (int j = 0; j < m_numOfUnits; j++)
+ {
+ Ptr<IeBeaconTimingUnit> new_element = Create<IeBeaconTimingUnit> ();
+ new_element->SetAid (i.ReadU8 ());
+ new_element->SetLastBeacon (i.ReadLsbtohU16 ());
+ new_element->SetBeaconInterval (i.ReadLsbtohU16 ());
+ m_neighbours.push_back (new_element);
+ }
+ return i.GetDistanceFrom (start);
+}
+;
+uint16_t
+IeBeaconTiming::TimestampToU16 (Time t)
+{
+ return ((uint16_t) ((t.GetMicroSeconds () >> 8) & 0xffff));
+}
+;
+
+uint16_t
+IeBeaconTiming::BeaconIntervalToU16 (Time t)
+{
+ return ((uint16_t) (t.GetMicroSeconds () >> 10) & 0xffff);
+}
+uint8_t
+IeBeaconTiming::AidToU8 (uint16_t x)
+{
+ return (uint8_t) (x & 0xff);
+}
+bool
+operator== (const IeBeaconTimingUnit & a, const IeBeaconTimingUnit & b)
+{
+ return ((a.GetAid () == b.GetAid ()) && (a.GetLastBeacon () == b.GetLastBeacon ())
+ && (a.GetBeaconInterval () == b.GetBeaconInterval ()));
+}
+bool
+operator== (const IeBeaconTiming & a, const IeBeaconTiming& b)
+{
+ if (a.m_numOfUnits != b.m_numOfUnits)
+ {
+ return false;
+ }
+ for (unsigned int i = 0; i < a.m_neighbours.size (); i++)
+ {
+ if (!(*PeekPointer (a.m_neighbours[i]) == *PeekPointer (b.m_neighbours[i])))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+std::ostream &
+operator << (std::ostream &os, const IeBeaconTiming &a)
+{
+ a.Print (os);
+ return os;
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-beacon-timing.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef WIFI_TIMING_ELEMENT_H
+#define WIFI_TIMING_ELEMENT_H
+
+#include <vector>
+#include "ns3/nstime.h"
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief Describes one unit of beacon timing element
+ */
+class IeBeaconTimingUnit : public RefCountBase
+{
+public:
+ IeBeaconTimingUnit ();
+ void SetAid (uint8_t aid);
+ void SetLastBeacon (uint16_t last_beacon);
+ void SetBeaconInterval (uint16_t beacon_interval);
+
+ uint8_t GetAid () const;
+ uint16_t GetLastBeacon () const;
+ uint16_t GetBeaconInterval () const;
+
+private:
+ /// Least significant octet of AID:
+ uint8_t m_aid;
+ /// Last time we received a beacon in accordance with a local TSF measured in 256 microseconds unit
+ uint16_t m_lastBeacon;
+ /// Beacon interval of remote mesh point
+ uint16_t m_beaconInterval;
+ friend bool operator== (const IeBeaconTimingUnit & a, const IeBeaconTimingUnit & b);
+};
+
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.89 of 802.11s draft 2.07
+ */
+class IeBeaconTiming : public WifiInformationElement
+{
+public:
+ /**
+ * \ingroup dot11s
+ * This type is a list of timing elements obtained from neigbours with their beacons:
+ */
+ typedef std::vector< Ptr<IeBeaconTimingUnit> > NeighboursTimingUnitsList;
+
+ IeBeaconTiming ();
+ /**
+ * This methods are needed for beacon collision
+ * avoidance module:
+ */
+ NeighboursTimingUnitsList GetNeighboursTimingElementsList ();
+ void AddNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon,
+ Time beacon_interval
+ );
+ void DelNeighboursTimingElementUnit (
+ uint16_t aid,
+ Time last_beacon,
+ Time beacon_interval
+ );
+ void ClearTimingElement ();
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual uint8_t GetInformationSize () const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ virtual void Print (std::ostream& os) const;
+ ///\}
+private:
+ /**
+ * Converters:
+ */
+ static uint16_t TimestampToU16 (Time x);
+ static uint16_t BeaconIntervalToU16 (Time x);
+ static uint8_t AidToU8 (uint16_t x);
+
+ NeighboursTimingUnitsList m_neighbours;
+ /**
+ * Timing element parameters:
+ */
+ uint16_t m_numOfUnits;
+ friend bool operator== (const IeBeaconTiming & a, const IeBeaconTiming & b);
+};
+bool operator== (const IeBeaconTiming & a, const IeBeaconTiming & b);
+bool operator== (const IeBeaconTimingUnit & a, const IeBeaconTimingUnit & b);
+std::ostream &operator << (std::ostream &os, const IeBeaconTiming &beaconTiming);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-configuration.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,224 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+#include "ie-dot11s-configuration.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+
+Dot11sMeshCapability::Dot11sMeshCapability () :
+ acceptPeerLinks (true), MCCASupported (false), MCCAEnabled (false), forwarding (true), beaconTimingReport (
+ true), TBTTAdjustment (true), powerSaveLevel (false)
+{
+}
+uint8_t
+Dot11sMeshCapability::GetSerializedSize () const
+{
+ return 2;
+}
+uint16_t
+Dot11sMeshCapability::GetUint16 () const
+{
+ uint16_t result = 0;
+ if (acceptPeerLinks)
+ {
+ result |= 1 << 0;
+ }
+ if (MCCASupported)
+ {
+ result |= 1 << 1;
+ }
+ if (MCCAEnabled)
+ {
+ result |= 1 << 2;
+ }
+ if (forwarding)
+ {
+ result |= 1 << 3;
+ }
+ if (beaconTimingReport)
+ {
+ result |= 1 << 4;
+ }
+ if (TBTTAdjustment)
+ {
+ result |= 1 << 5;
+ }
+ if (powerSaveLevel)
+ {
+ result |= 1 << 6;
+ }
+ return result;
+}
+Buffer::Iterator
+Dot11sMeshCapability::Serialize (Buffer::Iterator i) const
+{
+ i.WriteHtolsbU16 (GetUint16 ());
+ return i;
+}
+Buffer::Iterator
+Dot11sMeshCapability::Deserialize (Buffer::Iterator i)
+{
+ uint16_t cap = i.ReadLsbtohU16 ();
+ acceptPeerLinks = Is (cap, 0);
+ MCCASupported = Is (cap, 1);
+ MCCAEnabled = Is (cap, 2);
+ forwarding = Is (cap, 3);
+ beaconTimingReport = Is (cap, 4);
+ TBTTAdjustment = Is (cap, 5);
+ powerSaveLevel = Is (cap, 6);
+ return i;
+}
+bool
+Dot11sMeshCapability::Is (uint16_t cap, uint8_t n) const
+{
+ uint16_t mask = 1 << n;
+ return (cap & mask);
+}
+WifiElementId
+IeConfiguration::ElementId () const
+{
+ return IE11S_MESH_CONFIGURATION;
+}
+
+IeConfiguration::IeConfiguration () :
+ m_APSPId (PROTOCOL_HWMP), m_APSMId (METRIC_AIRTIME), m_CCMId (CONGESTION_NULL), m_SPId (
+ SYNC_NEIGHBOUR_OFFSET), m_APId (AUTH_NULL), m_neighbors (0)
+{
+}
+uint8_t
+IeConfiguration::GetInformationSize () const
+{
+ return 1 // Version
+ + 4 // APSPId
+ + 4 // APSMId
+ + 4 // CCMId
+ + 4 // SPId
+ + 4 // APId
+ + 1 // Mesh formation info (see 7.3.2.86.6 of 802.11s draft 3.0)
+ + m_meshCap.GetSerializedSize ();
+}
+void
+IeConfiguration::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (1); //Version
+ // Active Path Selection Protocol ID:
+ i.WriteHtolsbU32 (m_APSPId);
+ // Active Path Metric ID:
+ i.WriteHtolsbU32 (m_APSMId);
+ // Congestion Control Mode ID:
+ i.WriteHtolsbU32 (m_CCMId);
+ // Sync:
+ i.WriteHtolsbU32 (m_SPId);
+ // Auth:
+ i.WriteHtolsbU32 (m_APId);
+ i.WriteU8 (m_neighbors << 1);
+ m_meshCap.Serialize (i);
+}
+uint8_t
+IeConfiguration::DeserializeInformation (Buffer::Iterator i, uint8_t length)
+{
+ Buffer::Iterator start = i;
+ uint8_t version;
+ version = i.ReadU8 ();
+ // Active Path Selection Protocol ID:
+ m_APSPId = (dot11sPathSelectionProtocol) i.ReadLsbtohU32 ();
+ // Active Path Metric ID:
+ m_APSMId = (dot11sPathSelectionMetric) i.ReadLsbtohU32 ();
+ // Congestion Control Mode ID:
+ m_CCMId = (dot11sCongestionControlMode) i.ReadLsbtohU32 ();
+ m_SPId = (dot11sSynchronizationProtocolIdentifier) i.ReadLsbtohU32 ();
+ m_APId = (dot11sAuthenticationProtocol) i.ReadLsbtohU32 ();
+ m_neighbors = (i.ReadU8 () >> 1) & 0xF;
+ i = m_meshCap.Deserialize (i);
+ return i.GetDistanceFrom (start);
+}
+void
+IeConfiguration::Print (std::ostream& os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << "Number of neighbors: = " << (uint16_t) m_neighbors
+ << std::endl << "Active Path Selection Protocol ID: = " << (uint32_t) m_APSPId
+ << std::endl << "Active Path Selection Metric ID: = " << (uint32_t) m_APSMId
+ << std::endl << "Congestion Control Mode ID: = " << (uint32_t) m_CCMId
+ << std::endl << "Synchronize protocol ID: = " << (uint32_t) m_SPId
+ << std::endl << "Authentication protocol ID: = " << (uint32_t) m_APId
+ << std::endl << "Capabilities: = " << m_meshCap.GetUint16 () << std::endl;
+ os << "</information_element>" << std::endl;
+}
+void
+IeConfiguration::SetRouting (dot11sPathSelectionProtocol routingId)
+{
+ m_APSPId = routingId;
+}
+void
+IeConfiguration::SetMetric (dot11sPathSelectionMetric metricId)
+{
+ m_APSMId = metricId;
+}
+bool
+IeConfiguration::IsHWMP ()
+{
+ return (m_APSPId == PROTOCOL_HWMP);
+}
+bool
+IeConfiguration::IsAirtime ()
+{
+ return (m_APSMId == METRIC_AIRTIME);
+}
+void
+IeConfiguration::SetNeighborCount (uint8_t neighbors)
+{
+ m_neighbors = (neighbors > 31) ? 31 : neighbors;
+}
+uint8_t
+IeConfiguration::GetNeighborCount ()
+{
+ return m_neighbors;
+}
+Dot11sMeshCapability const&
+IeConfiguration::MeshCapability ()
+{
+ return m_meshCap;
+}
+bool
+operator== (const Dot11sMeshCapability & a, const Dot11sMeshCapability & b)
+{
+ return ((a.acceptPeerLinks == b.acceptPeerLinks) && (a.MCCASupported == b.MCCASupported) && (a.MCCAEnabled
+ == b.MCCAEnabled) && (a.forwarding == b.forwarding) && (a.beaconTimingReport == b.beaconTimingReport)
+ && (a.TBTTAdjustment == b.TBTTAdjustment) && (a.powerSaveLevel == b.powerSaveLevel));
+}
+bool
+operator== (const IeConfiguration & a, const IeConfiguration & b)
+{
+ return ((a.m_APSPId == b.m_APSPId) && (a.m_APSMId == b.m_APSMId) && (a.m_CCMId == b.m_CCMId) && (a.m_SPId
+ == b.m_SPId) && (a.m_APId == b.m_APId) && (a.m_neighbors == b.m_neighbors) && (a.m_meshCap
+ == b.m_meshCap));
+}
+std::ostream &
+operator << (std::ostream &os, const IeConfiguration &a)
+{
+ a.Print (os);
+ return os;
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-configuration.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#ifndef MESH_CONFIGURATION_H
+#define MESH_CONFIGURATION_H
+
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.1 in 802.11s draft 3.0
+ */
+enum dot11sPathSelectionProtocol
+{
+ PROTOCOL_HWMP = 0x000fac00,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.2 in 802.11s draft 3.0
+ */
+enum dot11sPathSelectionMetric
+{
+ METRIC_AIRTIME = 0x000fac00,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.3 in 802.11s draft 3.0
+ */
+enum dot11sCongestionControlMode
+{
+ CONGESTION_SIGNALING = 0x000fac00,
+ CONGESTION_NULL = 0x000facff,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.4 in 802.11s draft 3.0
+ */
+enum dot11sSynchronizationProtocolIdentifier
+{
+ SYNC_NEIGHBOUR_OFFSET = 0x000fac00,
+ SYNC_NULL = 0x000facff,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.5 in 802.11s draft 3.0
+ */
+enum dot11sAuthenticationProtocol
+{
+ AUTH_NULL = 0x000fac00,
+ AUTH_SAE = 0x000fac01,
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.86.7 in 802.11s draft 3.0
+ */
+class Dot11sMeshCapability
+{
+public:
+ Dot11sMeshCapability ();
+ uint8_t GetSerializedSize () const;
+ Buffer::Iterator Serialize (Buffer::Iterator i) const;
+ Buffer::Iterator Deserialize (Buffer::Iterator i);
+ uint16_t GetUint16 () const;
+ bool acceptPeerLinks;
+ bool MCCASupported;
+ bool MCCAEnabled;
+ bool forwarding;
+ bool beaconTimingReport;
+ bool TBTTAdjustment;
+ bool powerSaveLevel;
+ bool Is (uint16_t cap,uint8_t n) const;
+ friend bool operator== (const Dot11sMeshCapability & a, const Dot11sMeshCapability & b);
+};
+
+/**
+ * \ingroup dot11s
+ * \brief Describes Mesh Configuration Element
+ * see 7.3.2.86 of 802.11s draft 3.0
+ */
+class IeConfiguration : public WifiInformationElement
+{
+public:
+ IeConfiguration ();
+ void SetRouting (dot11sPathSelectionProtocol routingId);
+ void SetMetric (dot11sPathSelectionMetric metricId);
+ bool IsHWMP ();
+ bool IsAirtime ();
+ void SetNeighborCount (uint8_t neighbors);
+ uint8_t GetNeighborCount ();
+ Dot11sMeshCapability const& MeshCapability ();
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual uint8_t GetInformationSize () const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ virtual void Print (std::ostream& os) const;
+ ///\}
+private:
+ /** Active Path Selection Protocol ID */
+ dot11sPathSelectionProtocol m_APSPId;
+ /** Active Path Metric ID */
+ dot11sPathSelectionMetric m_APSMId;
+ /** Congestion Control Mode ID */
+ dot11sCongestionControlMode m_CCMId;
+ /** Sync protocol ID */
+ dot11sSynchronizationProtocolIdentifier m_SPId;
+ /** Auth protocol ID */
+ dot11sAuthenticationProtocol m_APId;
+ Dot11sMeshCapability m_meshCap;
+ uint8_t m_neighbors;
+ friend bool operator== (const IeConfiguration & a, const IeConfiguration & b);
+};
+bool operator== (const IeConfiguration & a, const IeConfiguration & b);
+bool operator== (const Dot11sMeshCapability & a, const Dot11sMeshCapability & b);
+std::ostream &operator << (std::ostream &os, const IeConfiguration &config);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-id.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-id.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+namespace dot11s {
+IeMeshId::IeMeshId ()
+{
+ for (uint8_t i = 0; i < 32; i++)
+ {
+ m_meshId[i] = 0;
+ }
+}
+IeMeshId::IeMeshId (std::string s)
+{
+ NS_ASSERT (s.size () < 32);
+ const char *meshid = s.c_str ();
+ uint8_t len = 0;
+ while (*meshid != 0 && len < 32)
+ {
+ m_meshId[len] = *meshid;
+ meshid++;
+ len++;
+ }
+ NS_ASSERT (len <= 32);
+ while (len < 33)
+ {
+ m_meshId[len] = 0;
+ len++;
+ }
+}
+WifiElementId
+IeMeshId::ElementId () const
+{
+ return IE11S_MESH_ID;
+}
+bool
+IeMeshId::IsEqual (IeMeshId const &o) const
+{
+ uint8_t i = 0;
+ while (i < 32 && m_meshId[i] == o.m_meshId[i] && m_meshId[i] != 0)
+ {
+ i++;
+ }
+ if (m_meshId[i] != o.m_meshId[i])
+ {
+ return false;
+ }
+ return true;
+}
+bool
+IeMeshId::IsBroadcast (void) const
+{
+ if (m_meshId[0] == 0)
+ {
+ return true;
+ }
+ return false;
+}
+char *
+IeMeshId::PeekString (void) const
+{
+ return (char *) m_meshId;
+}
+uint8_t
+IeMeshId::GetInformationSize (void) const
+{
+ uint8_t size = 0;
+ while (m_meshId[size] != 0 && size < 32)
+ {
+ size++;
+ }
+ NS_ASSERT (size <= 32);
+ return size;
+}
+void
+IeMeshId::SerializeInformation (Buffer::Iterator i) const
+{
+ uint8_t size = 0;
+ while (m_meshId[size] != 0 && size < 32)
+ {
+ i.WriteU8 (m_meshId[size]);
+ size++;
+ }
+}
+uint8_t
+IeMeshId::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ NS_ASSERT (length <= 32);
+ i.Read (m_meshId, length);
+ m_meshId[length] = 0;
+ return i.GetDistanceFrom (start);
+}
+void
+IeMeshId::Print (std::ostream& os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << "meshId = " << PeekString ();
+ os << "</information_element>" << std::endl;
+}
+bool
+operator== (const IeMeshId & a, const IeMeshId & b)
+{
+ bool result (true);
+ uint8_t size = 0;
+
+ while (size < 32)
+ {
+ result = result && (a.m_meshId[size] == b.m_meshId[size]);
+ if (a.m_meshId[size] == 0)
+ {
+ return result;
+ }
+ size++;
+ }
+ return result;
+}
+std::ostream &
+operator << (std::ostream &os, const IeMeshId &a)
+{
+ a.Print (os);
+ return os;
+}
+} //namespace dot11s
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-id.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef MESH_ID_H
+#define MESH_ID_H
+
+#include <stdint.h>
+#include "ns3/buffer.h"
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \brief a IEEE 802.11s Mesh ID 7.3.287 of 802.11s draft 3.0
+ *
+ */
+class IeMeshId : public WifiInformationElement
+{
+public:
+ // broadcast meshId
+ IeMeshId ();
+ IeMeshId (std::string s);
+
+ bool IsEqual (IeMeshId const &o) const;
+ bool IsBroadcast (void) const;
+ uint32_t GetLength (void) const;
+ char *PeekString (void) const;
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ virtual void Print (std::ostream& os) const;
+ virtual uint8_t GetInformationSize () const;
+ ///\}
+private:
+ uint8_t m_meshId[33];
+ friend bool operator== (const IeMeshId & a, const IeMeshId & b);
+};
+
+std::ostream &operator << (std::ostream &os, const IeMeshId &meshId);
+
+/**
+ * \class ns3::IeMeshIdValue
+ * \brief hold objects of type ns3::IeMeshId
+ */
+
+ATTRIBUTE_HELPER_HEADER (IeMeshId);
+} //namespace dot11s
+} // namespace ns3
+#endif /* MESH_ID_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-metric-report.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-metric-report.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+namespace dot11s {
+IeLinkMetricReport::IeLinkMetricReport () :
+ m_metric (0)
+{
+}
+IeLinkMetricReport::IeLinkMetricReport (uint32_t metric)
+{
+ m_metric = metric;
+}
+WifiElementId
+IeLinkMetricReport::ElementId () const
+{
+ return IE11S_LINK_METRIC_REPORT;
+}
+uint8_t
+IeLinkMetricReport::GetInformationSize (void) const
+{
+ return sizeof (uint32_t);
+}
+uint32_t
+IeLinkMetricReport::GetMetric ()
+{
+ return m_metric;
+}
+void
+IeLinkMetricReport::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IeLinkMetricReport::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteHtolsbU32 (m_metric);
+}
+uint8_t
+IeLinkMetricReport::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_metric = i.ReadLsbtohU32 ();
+ return i.GetDistanceFrom (start);
+}
+void
+IeLinkMetricReport::Print (std::ostream& os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << "Metric = " << m_metric;
+ os << "</information_element>" << std::endl;
+}
+bool
+operator== (const IeLinkMetricReport & a, const IeLinkMetricReport & b)
+{
+ return (a.m_metric == b.m_metric);
+}
+std::ostream &
+operator << (std::ostream &os, const IeLinkMetricReport &a)
+{
+ a.Print (os);
+ return os;
+}
+} //namespace dot11s
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-metric-report.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef METRIC_REPORT_H
+#define METRIC_REPORT_H
+
+#include <stdint.h>
+#include "ns3/buffer.h"
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \brief a IEEE 802.11s Mesh ID 7.3.2.88 of 802.11s draft 3.0
+ *
+ */
+class IeLinkMetricReport : public WifiInformationElement
+{
+public:
+ IeLinkMetricReport ();
+ IeLinkMetricReport (uint32_t metric);
+ void SetMetric (uint32_t metric);
+ uint32_t GetMetric ();
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ virtual void Print (std::ostream& os) const;
+ virtual uint8_t GetInformationSize () const;
+ ///\}
+private:
+ uint32_t m_metric;
+ friend bool operator== (const IeLinkMetricReport & a, const IeLinkMetricReport & b);
+ friend bool operator> (const IeLinkMetricReport & a, const IeLinkMetricReport & b);
+ friend bool operator< (const IeLinkMetricReport & a, const IeLinkMetricReport & b);
+};
+std::ostream &operator << (std::ostream &os, const IeLinkMetricReport &linkMetricReport);
+} //namespace dot11s
+} // namespace ns3
+#endif /* METRIC_REPORT_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peer-management.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+#include "ie-dot11s-peer-management.h"
+#include "ns3/assert.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dot11s {
+
+IePeerManagement::IePeerManagement () :
+ m_length (3), m_subtype (PEER_OPEN), m_localLinkId (0), m_peerLinkId (0), m_reasonCode (REASON11S_RESERVED)
+{
+}
+WifiElementId
+IePeerManagement::ElementId () const
+{
+ return IE11S_PEERING_MANAGEMENT;
+}
+void
+IePeerManagement::SetPeerOpen (uint16_t localLinkId)
+{
+ m_length = 3;
+ m_subtype = PEER_OPEN;
+ m_localLinkId = localLinkId;
+}
+void
+IePeerManagement::SetPeerClose (uint16_t localLinkId, uint16_t peerLinkId, PmpReasonCode reasonCode)
+{
+ m_length = 7;
+ m_subtype = PEER_CLOSE;
+ m_localLinkId = localLinkId;
+ m_peerLinkId = peerLinkId;
+ m_reasonCode = reasonCode;
+}
+
+void
+IePeerManagement::SetPeerConfirm (uint16_t localLinkId, uint16_t peerLinkId)
+{
+ m_length = 5;
+ m_subtype = PEER_CONFIRM;
+ m_localLinkId = localLinkId;
+ m_peerLinkId = peerLinkId;
+}
+
+PmpReasonCode
+IePeerManagement::GetReasonCode () const
+{
+ return m_reasonCode;
+}
+
+uint16_t
+IePeerManagement::GetLocalLinkId () const
+{
+ return m_localLinkId;
+}
+
+uint16_t
+IePeerManagement::GetPeerLinkId () const
+{
+ return m_peerLinkId;
+}
+
+uint8_t
+IePeerManagement::GetInformationSize (void) const
+{
+ return m_length;
+}
+uint8_t
+IePeerManagement::GetSubtype () const
+{
+ return m_subtype;
+}
+bool
+IePeerManagement::SubtypeIsOpen () const
+{
+ return (m_subtype == PEER_OPEN);
+}
+bool
+IePeerManagement::SubtypeIsClose () const
+{
+ return (m_subtype == PEER_CLOSE);
+}
+bool
+IePeerManagement::SubtypeIsConfirm () const
+{
+ return (m_subtype == PEER_CONFIRM);
+}
+
+void
+IePeerManagement::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_subtype);
+ i.WriteHtolsbU16 (m_localLinkId);
+ if (m_length > 3)
+ {
+ i.WriteHtolsbU16 (m_peerLinkId);
+ }
+ if (m_length > 5)
+ {
+ i.WriteHtolsbU16 (m_reasonCode);
+ }
+}
+uint8_t
+IePeerManagement::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_subtype = i.ReadU8 ();
+ m_length = length;
+ if (m_subtype == PEER_OPEN)
+ {
+ NS_ASSERT (length == 3);
+ }
+ if (m_subtype == PEER_CONFIRM)
+ {
+ NS_ASSERT (length == 5);
+ }
+ if (m_subtype == PEER_CLOSE)
+ {
+ NS_ASSERT (length == 7);
+ }
+ m_localLinkId = i.ReadLsbtohU16 ();
+ if (m_length > 3)
+ {
+ m_peerLinkId = i.ReadLsbtohU16 ();
+ }
+ if (m_length > 5)
+ {
+ m_reasonCode = (PmpReasonCode) i.ReadLsbtohU16 ();
+ }
+ return i.GetDistanceFrom (start);
+}
+void
+IePeerManagement::Print (std::ostream& os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << " Subtype: = " << (uint16_t) m_subtype << std::endl;
+ os << " Length: = " << (uint16_t) m_length << std::endl;
+ os << " LocalLinkId: = " << m_localLinkId << std::endl;
+ os << " PeerLinkId: = " << m_peerLinkId << std::endl;
+ os << " ReasonCode: = " << m_reasonCode << std::endl;
+ os << "</information_element>" << std::endl;
+}
+bool
+operator== (const IePeerManagement & a, const IePeerManagement & b)
+{
+ return ((a.m_length == b.m_length) && (a.m_subtype == b.m_subtype) && (a.m_localLinkId == b.m_localLinkId)
+ && (a.m_peerLinkId == b.m_peerLinkId) && (a.m_reasonCode == b.m_reasonCode));
+}
+std::ostream &
+operator << (std::ostream &os, const IePeerManagement &a)
+{
+ a.Print (os);
+ return os;
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peer-management.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+#ifndef MESH_PEER_MAN_ELEMENT
+#define MESH_PEER_MAN_ELEMENT
+
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3 {
+namespace dot11s {
+
+/**
+ * \ingroup dot11s
+ * \brief Codes used by 802.11s Peer Management Protocol
+ */
+enum PmpReasonCode
+{
+ REASON11S_PEERING_CANCELLED = 2, // according to open80211s
+ REASON11S_MESH_MAX_PEERS,
+ REASON11S_MESH_CAPABILITY_POLICY_VIOLATION,
+ REASON11S_MESH_CLOSE_RCVD,
+ REASON11S_MESH_MAX_RETRIES,
+ REASON11S_MESH_CONFIRM_TIMEOUT,
+ REASON11S_MESH_INVALID_GTK,
+ REASON11S_MESH_INCONSISTENT_PARAMETERS,
+ REASON11S_MESH_INVALID_SECURITY_CAPABILITY,
+ REASON11S_RESERVED,
+};
+
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.85 of draft 2.07
+ */
+class IePeerManagement : public WifiInformationElement
+{
+public:
+ IePeerManagement ();
+ enum Subtype
+ {
+ PEER_OPEN = 0,
+ PEER_CONFIRM,
+ PEER_CLOSE,
+ };
+ void SetPeerOpen (uint16_t localLinkId);
+ void SetPeerClose (uint16_t localLinkID, uint16_t peerLinkId, PmpReasonCode reasonCode);
+ void SetPeerConfirm (uint16_t localLinkID, uint16_t peerLinkId);
+
+ PmpReasonCode GetReasonCode () const;
+ uint16_t GetLocalLinkId () const;
+ uint16_t GetPeerLinkId () const;
+ bool SubtypeIsOpen () const;
+ bool SubtypeIsClose () const;
+ bool SubtypeIsConfirm () const ;
+ uint8_t GetSubtype () const;
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual uint8_t GetInformationSize (void) const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ virtual void Print (std::ostream& os) const;
+ ///\}
+private:
+ uint8_t m_length;
+ uint8_t m_subtype;
+ uint16_t m_localLinkId;
+ /**
+ * Present within confirm and may be present in close
+ */
+ uint16_t m_peerLinkId;
+ /**
+ * Present only within close frame
+ */
+ PmpReasonCode m_reasonCode;
+ friend bool operator== (const IePeerManagement & a, const IePeerManagement & b);
+};
+bool operator== (const IePeerManagement & a, const IePeerManagement & b);
+std::ostream &operator << (std::ostream &os, const IePeerManagement &peerMan);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peering-protocol.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-peering-protocol.h"
+namespace ns3 {
+namespace dot11s {
+uint8_t
+IePeeringProtocol::GetInformationSize () const
+{
+ return 1;
+}
+IePeeringProtocol::IePeeringProtocol () :
+ m_protocol (0)
+{
+}
+WifiElementId
+IePeeringProtocol::ElementId () const
+{
+ return IE11S_MESH_PEERING_PROTOCOL_VERSION;
+}
+void
+IePeeringProtocol::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_protocol);
+}
+uint8_t
+IePeeringProtocol::DeserializeInformation (Buffer::Iterator i, uint8_t length)
+{
+ Buffer::Iterator start = i;
+ m_protocol = i.ReadU8 ();
+ return i.GetDistanceFrom (start);
+}
+void
+IePeeringProtocol::Print (std::ostream& os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << "peering protocol = " << m_protocol;
+ os << "</information_element>" << std::endl;
+}
+std::ostream &
+operator << (std::ostream &os, const IePeeringProtocol &a)
+{
+ a.Print (os);
+ return os;
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-peering-protocol.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef MESH_PERING_PROTOCOL_H
+#define MESH_PEERING_PROTOCOL_H
+
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3
+{
+namespace dot11s
+{
+class IePeeringProtocol : public WifiInformationElement
+{
+public:
+ IePeeringProtocol ();
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual uint8_t GetInformationSize () const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ virtual void Print (std::ostream& os) const;
+ ///\}
+private:
+ uint8_t m_protocol;
+};
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-perr.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-perr.h"
+#include "ns3/address-utils.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+IePerr::IePerr ()
+{
+}
+IePerr::~IePerr ()
+{
+}
+WifiElementId
+IePerr::ElementId () const
+{
+ return IE11S_PERR;
+}
+void
+IePerr::Print (std::ostream &os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << "Number of failed destinations: = " << m_addressUnits.size ();
+ for (unsigned int j = 0; j < m_addressUnits.size (); j++)
+ {
+ os << "Failed destination address: = " << m_addressUnits[j].destination << ", sequence number = "
+ << m_addressUnits[j].seqnum;
+ }
+ os << std::endl << "</information_element>" << std::endl;
+}
+uint8_t
+IePerr::GetNumOfDest ()
+{
+ return m_addressUnits.size ();
+}
+void
+IePerr::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (0);
+ i.WriteU8 (m_addressUnits.size ());
+ for (unsigned int j = 0; j < m_addressUnits.size (); j++)
+ {
+ WriteTo (i, m_addressUnits[j].destination);
+ i.WriteHtolsbU32 (m_addressUnits[j].seqnum);
+ }
+}
+uint8_t
+IePerr::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ i.Next (1); //Mode flags is not used now
+ uint8_t numOfDest = i.ReadU8 ();
+ NS_ASSERT ((2 + 10 * numOfDest ) == length);
+ length = 0; //to avoid compiler warning in optimized builds
+ for (unsigned int j = 0; j < numOfDest; j++)
+ {
+ FailedDestination unit;
+ ReadFrom (i, unit.destination);
+ unit.seqnum = i.ReadLsbtohU32 ();
+ m_addressUnits.push_back (unit);
+ }
+ return i.GetDistanceFrom (start);
+}
+
+uint8_t
+IePerr::GetInformationSize () const
+{
+ uint8_t retval = 1 //ModeFlags
+ + 1 //NumOfDests
+ + (6 + 4) * m_addressUnits.size ();
+ return retval;
+}
+
+void
+IePerr::AddAddressUnit (FailedDestination unit)
+{
+ for (unsigned int i = 0; i < m_addressUnits.size (); i++)
+ {
+ if (m_addressUnits[i].destination == unit.destination)
+ {
+ return;
+ }
+ }
+ if ((m_addressUnits.size () + 1) * 10 + 2 > 255)
+ {
+ return;
+ }
+ m_addressUnits.push_back (unit);
+}
+bool
+IePerr::IsFull () const
+{
+ return (GetInformationSize () + 2 /* ID + LENGTH*/+ 10 /* Sie of Mac48Address + uint32_t (one unit)*/> 255);
+}
+std::vector<IePerr::FailedDestination>
+IePerr::GetAddressUnitVector () const
+{
+ return m_addressUnits;
+}
+void
+IePerr::DeleteAddressUnit (Mac48Address address)
+{
+ for (std::vector<FailedDestination>::iterator i = m_addressUnits.begin (); i != m_addressUnits.end (); i++)
+ {
+ if (i->destination == address)
+ {
+ m_addressUnits.erase (i);
+ break;
+ }
+ }
+}
+void
+IePerr::ResetPerr ()
+{
+ m_addressUnits.clear ();
+}
+bool
+operator== (const IePerr & a, const IePerr & b)
+{
+ if (a.m_addressUnits.size () != b.m_addressUnits.size ())
+ {
+ return false;
+ }
+ for (unsigned int i = 0; i < a.m_addressUnits.size (); i++)
+ {
+ if (a.m_addressUnits[i].destination != b.m_addressUnits[i].destination)
+ {
+ return false;
+ }
+ if (a.m_addressUnits[i].seqnum != b.m_addressUnits[i].seqnum)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+std::ostream &
+operator << (std::ostream &os, const IePerr &a)
+{
+ a.Print (os);
+ return os;
+}
+} // namespace dot11s
+} //namespace ns3
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-perr.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef PERR_INFORMATION_ELEMENT_H
+#define PERR_INFORMATION_ELEMENT_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.98 of 802.11s draft 2.07
+ */
+class IePerr : public WifiInformationElement
+{
+public:
+ IePerr ();
+ ~IePerr ();
+ struct FailedDestination
+ {
+ Mac48Address destination;
+ uint32_t seqnum;
+ };
+ uint8_t GetNumOfDest ();
+
+ void AddAddressUnit (struct FailedDestination unit);
+ bool IsFull () const;
+ std::vector<FailedDestination> GetAddressUnitVector () const;
+ void DeleteAddressUnit (Mac48Address address);
+ void ResetPerr ();
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ virtual void Print (std::ostream& os) const;
+ virtual uint8_t GetInformationSize () const;
+ ///\}
+private:
+ std::vector<FailedDestination> m_addressUnits;
+ friend bool operator== (const IePerr & a, const IePerr & b);
+};
+ bool operator== (const IePerr & a, const IePerr & b);
+ std::ostream &operator << (std::ostream &os, const IePerr &perr);
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-prep.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,214 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-prep.h"
+#include "ns3/address-utils.h"
+#include "ns3/assert.h"
+#include "ns3/packet.h"
+namespace ns3 {
+namespace dot11s {
+/********************************
+ * IePrep
+ *******************************/
+IePrep::~IePrep ()
+{
+}
+IePrep::IePrep () :
+ m_flags (0), m_hopcount (0), m_ttl (0), m_destinationAddress (Mac48Address::GetBroadcast ()),
+ m_destSeqNumber (0), m_lifetime (0), m_metric (0), m_originatorAddress (Mac48Address::GetBroadcast ()),
+ m_originatorSeqNumber (0)
+{
+}
+WifiElementId
+IePrep::ElementId () const
+{
+ return IE11S_PREP;
+}
+void
+IePrep::SetFlags (uint8_t flags)
+{
+ m_flags = flags;
+}
+void
+IePrep::SetHopcount (uint8_t hopcount)
+{
+ m_hopcount = hopcount;
+}
+void
+IePrep::SetTtl (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+void
+IePrep::SetDestinationSeqNumber (uint32_t dest_seq_number)
+{
+ m_destSeqNumber = dest_seq_number;
+}
+void
+IePrep::SetDestinationAddress (Mac48Address dest_address)
+{
+ m_destinationAddress = dest_address;
+}
+void
+IePrep::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IePrep::SetOriginatorAddress (Mac48Address originator_address)
+{
+ m_originatorAddress = originator_address;
+}
+void
+IePrep::SetOriginatorSeqNumber (uint32_t originator_seq_number)
+{
+ m_originatorSeqNumber = originator_seq_number;
+}
+void
+IePrep::SetLifetime (uint32_t lifetime)
+{
+ m_lifetime = lifetime;
+}
+uint8_t
+IePrep::GetFlags () const
+{
+ return m_flags;
+}
+uint8_t
+IePrep::GetHopcount () const
+{
+ return m_hopcount;
+}
+uint32_t
+IePrep::GetTtl () const
+{
+ return m_ttl;
+}
+uint32_t
+IePrep::GetDestinationSeqNumber () const
+{
+ return m_destSeqNumber;
+}
+Mac48Address
+IePrep::GetDestinationAddress () const
+{
+ return m_destinationAddress;
+}
+uint32_t
+IePrep::GetMetric () const
+{
+ return m_metric;
+}
+Mac48Address
+IePrep::GetOriginatorAddress () const
+{
+ return m_originatorAddress;
+}
+uint32_t
+IePrep::GetOriginatorSeqNumber () const
+{
+ return m_originatorSeqNumber;
+}
+uint32_t
+IePrep::GetLifetime () const
+{
+ return m_lifetime;
+}
+void
+IePrep::DecrementTtl ()
+{
+ m_ttl--;
+}
+
+void
+IePrep::IncrementMetric (uint32_t metric)
+{
+ m_metric += metric;
+}
+
+void
+IePrep::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_flags);
+ i.WriteU8 (m_hopcount);
+ i.WriteU8 (m_ttl);
+ WriteTo (i, m_destinationAddress);
+ i.WriteHtolsbU32 (m_destSeqNumber);
+ i.WriteHtolsbU32 (m_lifetime);
+ i.WriteHtolsbU32 (m_metric);
+ WriteTo (i, m_originatorAddress);
+ i.WriteHtolsbU32 (m_originatorSeqNumber);
+}
+uint8_t
+IePrep::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_flags = i.ReadU8 ();
+ m_hopcount = i.ReadU8 ();
+ m_ttl = i.ReadU8 ();
+ ReadFrom (i, m_destinationAddress);
+ m_destSeqNumber = i.ReadLsbtohU32 ();
+ m_lifetime = i.ReadLsbtohU32 ();
+ m_metric = i.ReadLsbtohU32 ();
+ ReadFrom (i, m_originatorAddress);
+ m_originatorSeqNumber = i.ReadLsbtohU32 ();
+ return i.GetDistanceFrom (start);
+}
+uint8_t
+IePrep::GetInformationSize () const
+{
+ uint32_t retval = 1 //Flags
+ + 1 //Hopcount
+ + 1 //Ttl
+ + 6 //Dest address
+ + 4 //Dest seqno
+ + 4 //Lifetime
+ + 4 //metric
+ + 6 //Originator address
+ + 4; //Originator seqno
+ return retval;
+}
+void
+IePrep::Print (std::ostream& os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << "Flags: = " << m_flags << std::endl << "Hopcount: = " << m_hopcount << std::endl << "TTL: = " << m_ttl
+ << std::endl<< "Destination: = " << m_destinationAddress << std::endl << "Dest. seqnum: = " << m_destSeqNumber
+ << std::endl << "Lifetime: = " << m_lifetime << std::endl<< "Metric: = " << m_metric << std::endl << "Originator: = "
+ << m_originatorAddress << std::endl << "Orig. seqnum: = " << m_originatorSeqNumber << std::endl;
+ os << "</information_element>" << std::endl;
+}
+bool
+operator== (const IePrep & a, const IePrep & b)
+{
+ return ((a.m_flags == b.m_flags) && (a.m_hopcount == b.m_hopcount) && (a.m_ttl == b.m_ttl)
+ && (a.m_destinationAddress == b.m_destinationAddress) && (a.m_destSeqNumber == b.m_destSeqNumber)
+ && (a.m_lifetime == b.m_lifetime) && (a.m_metric == b.m_metric) && (a.m_originatorAddress
+ == b.m_originatorAddress) && (a.m_originatorSeqNumber == b.m_originatorSeqNumber));
+}
+std::ostream &
+operator << (std::ostream &os, const IePrep &a)
+{
+ a.Print (os);
+ return os;
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-prep.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef WIFI_PREP_INFORMATION_ELEMENT_H
+#define WIFI_PREP_INFORMATION_ELEMENT_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.97 of 802.11s draft 2.07
+ */
+class IePrep : public WifiInformationElement
+{
+public:
+ IePrep ();
+ ~IePrep ();
+ void SetFlags (uint8_t flags);
+ void SetHopcount (uint8_t hopcount);
+ void SetTtl (uint8_t ttl);
+ void SetDestinationAddress (Mac48Address dest_address);
+ void SetDestinationSeqNumber (uint32_t dest_seq_number);
+ void SetLifetime (uint32_t lifetime);
+ void SetMetric (uint32_t metric);
+ void SetOriginatorAddress (Mac48Address originator_address);
+ void SetOriginatorSeqNumber (uint32_t originator_seq_number);
+
+ uint8_t GetFlags () const;
+ uint8_t GetHopcount () const;
+ uint32_t GetTtl () const;
+ Mac48Address GetDestinationAddress () const;
+ uint32_t GetDestinationSeqNumber () const;
+ uint32_t GetLifetime () const;
+ uint32_t GetMetric () const;
+ Mac48Address GetOriginatorAddress () const;
+ uint32_t GetOriginatorSeqNumber ()const ;
+
+ void DecrementTtl ();
+ void IncrementMetric (uint32_t metric);
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ virtual uint8_t GetInformationSize () const;
+ virtual void Print (std::ostream& os) const;
+ ///\}
+private:
+ uint8_t m_flags;
+ uint8_t m_hopcount;
+ uint8_t m_ttl;
+ Mac48Address m_destinationAddress;
+ uint32_t m_destSeqNumber;
+ uint32_t m_lifetime;
+ uint32_t m_metric;
+ Mac48Address m_originatorAddress;
+ uint32_t m_originatorSeqNumber;
+ friend bool operator== (const IePrep & a, const IePrep & b);
+};
+bool operator== (const IePrep & a, const IePrep & b);
+std::ostream &operator << (std::ostream &os, const IePrep &prep);
+} // namespace dot11s
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-preq.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,455 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-preq.h"
+#include "ns3/address-utils.h"
+#include "ns3/assert.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dot11s {
+/*************************
+ * DestinationAddressUnit
+ ************************/
+DestinationAddressUnit::DestinationAddressUnit () :
+ m_do (false), m_rf (false), m_usn (false), m_destinationAddress (Mac48Address ()), m_destSeqNumber (0)
+{
+}
+void
+DestinationAddressUnit::SetFlags (bool doFlag, bool rfFlag, bool usnFlag)
+{
+ m_do = doFlag;
+ m_rf = rfFlag;
+ m_usn = usnFlag;
+}
+
+void
+DestinationAddressUnit::SetDestSeqNumber (uint32_t dest_seq_number)
+{
+ m_destSeqNumber = dest_seq_number;
+ if (m_destSeqNumber != 0)
+ {
+ m_usn = true;
+ }
+}
+void
+DestinationAddressUnit::SetDestinationAddress (Mac48Address dest_address)
+{
+ m_destinationAddress = dest_address;
+}
+bool
+DestinationAddressUnit::IsDo ()
+{
+ return m_do;
+}
+
+bool
+DestinationAddressUnit::IsRf ()
+{
+ return m_rf;
+}
+bool
+DestinationAddressUnit::IsUsn ()
+{
+ return m_usn;
+}
+uint32_t
+DestinationAddressUnit::GetDestSeqNumber () const
+{
+ return m_destSeqNumber;
+}
+Mac48Address
+DestinationAddressUnit::GetDestinationAddress () const
+{
+ return m_destinationAddress;
+}
+/********************************
+ * IePreq
+ *******************************/
+IePreq::~IePreq ()
+{
+}
+IePreq::IePreq () :
+ m_maxSize (32), m_flags (0), m_hopCount (0), m_ttl (0), m_preqId (0), m_originatorAddress (
+ Mac48Address::GetBroadcast ()), m_originatorSeqNumber (0), m_lifetime (0), m_metric (0),
+ m_destCount (0)
+{
+}
+WifiElementId
+IePreq::ElementId () const
+{
+ return IE11S_PREQ;
+}
+void
+IePreq::SetUnicastPreq ()
+{
+ m_flags |= 1 << 1;
+}
+
+void
+IePreq::SetNeedNotPrep ()
+{
+ m_flags |= 1 << 2;
+}
+//void
+//IePreq::SetFlags (uint8_t flags)
+//{
+// m_flags = flags;
+//}
+void
+IePreq::SetHopcount (uint8_t hopcount)
+{
+ m_hopCount = hopcount;
+}
+void
+IePreq::SetTTL (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+void
+IePreq::SetPreqID (uint32_t preq_id)
+{
+ m_preqId = preq_id;
+}
+void
+IePreq::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IePreq::SetOriginatorAddress (Mac48Address originator_address)
+{
+ m_originatorAddress = originator_address;
+}
+void
+IePreq::SetOriginatorSeqNumber (uint32_t originator_seq_number)
+{
+ m_originatorSeqNumber = originator_seq_number;
+}
+void
+IePreq::SetLifetime (uint32_t lifetime)
+{
+ m_lifetime = lifetime;
+}
+void
+IePreq::SetDestCount (uint8_t dest_count)
+{
+ m_destCount = dest_count;
+}
+bool
+IePreq::IsUnicastPreq () const
+{
+ return (m_flags & (1 << 1));
+}
+bool
+IePreq::IsNeedNotPrep () const
+{
+ return (m_flags & (1 << 2));
+}
+uint8_t
+IePreq::GetHopCount () const
+{
+ return m_hopCount;
+}
+uint8_t
+IePreq::GetTtl () const
+{
+ return m_ttl;
+}
+uint32_t
+IePreq::GetPreqID () const
+{
+ return m_preqId;
+}
+uint32_t
+IePreq::GetMetric () const
+{
+ return m_metric;
+}
+Mac48Address
+IePreq::GetOriginatorAddress () const
+{
+ return m_originatorAddress;
+}
+uint32_t
+IePreq::GetOriginatorSeqNumber () const
+{
+ return m_originatorSeqNumber;
+}
+uint32_t
+IePreq::GetLifetime () const
+{
+ return m_lifetime;
+}
+
+uint8_t
+IePreq::GetDestCount () const
+{
+ return m_destCount;
+}
+void
+IePreq::DecrementTtl ()
+{
+ m_ttl--;
+ m_hopCount++;
+}
+void
+IePreq::IncrementMetric (uint32_t metric)
+{
+ m_metric += metric;
+}
+void
+IePreq::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_flags);
+ i.WriteU8 (m_hopCount);
+ i.WriteU8 (m_ttl);
+ i.WriteHtolsbU32 (m_preqId);
+ WriteTo (i, m_originatorAddress);
+ i.WriteHtolsbU32 (m_originatorSeqNumber);
+ i.WriteHtolsbU32 (m_lifetime);
+ i.WriteHtolsbU32 (m_metric);
+ i.WriteU8 (m_destCount);
+ int written = 0;
+ for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator j = m_destinations.begin (); j
+ != m_destinations.end (); j++)
+ {
+ uint8_t flags = 0;
+ if ((*j)->IsDo ())
+ {
+ flags |= 1 << 0;
+ }
+ if ((*j)->IsRf ())
+ {
+ flags |= 1 << 1;
+ }
+ if ((*j)->IsUsn ())
+ {
+ flags |= 1 << 2;
+ }
+ i.WriteU8 (flags);
+ WriteTo (i, (*j)->GetDestinationAddress ());
+ i.WriteHtolsbU32 ((*j)->GetDestSeqNumber ());
+ written++;
+ if (written > m_maxSize)
+ {
+ break;
+ }
+ }
+}
+uint8_t
+IePreq::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_flags = i.ReadU8 ();
+ m_hopCount = i.ReadU8 ();
+ m_ttl = i.ReadU8 ();
+ m_preqId = i.ReadLsbtohU32 ();
+ ReadFrom (i, m_originatorAddress);
+ m_originatorSeqNumber = i.ReadLsbtohU32 ();
+ m_lifetime = i.ReadLsbtohU32 ();
+ m_metric = i.ReadLsbtohU32 ();
+ m_destCount = i.ReadU8 ();
+ for (int j = 0; j < m_destCount; j++)
+ {
+ Ptr<DestinationAddressUnit> new_element = Create<DestinationAddressUnit> ();
+ bool doFlag = false;
+ bool rfFlag = false;
+ bool usnFlag = false;
+ uint8_t flags = i.ReadU8 ();
+ if (flags & (1 << 0))
+ {
+ doFlag = true;
+ }
+ if (flags & (1 << 1))
+ {
+ rfFlag = true;
+ }
+ if (flags & (1 << 2))
+ {
+ usnFlag = true;
+ }
+ new_element->SetFlags (doFlag, rfFlag, usnFlag);
+ Mac48Address addr;
+ ReadFrom (i, addr);
+ new_element->SetDestinationAddress (addr);
+ new_element->SetDestSeqNumber (i.ReadLsbtohU32 ());
+ m_destinations.push_back (new_element);
+ NS_ASSERT (28 + j * 11 < length);
+ }
+ return i.GetDistanceFrom (start);
+}
+uint8_t
+IePreq::GetInformationSize () const
+{
+ uint8_t retval = 1 //Flags
+ + 1 //Hopcount
+ + 1 //TTL
+ + 4 //PREQ ID
+ + 6 //Source address (originator)
+ + 4 //Originator seqno
+ + 4 //Lifetime
+ + 4 //metric
+ + 1; //destination count
+ if (m_destCount > m_maxSize)
+ {
+ retval += (m_maxSize * 11);
+ }
+ else
+ {
+ retval += (m_destCount * 11);
+ }
+ return retval;
+}
+void
+IePreq::Print (std::ostream &os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << " originator address = " << m_originatorAddress << "std::endl";
+ os << " TTL = " << (uint16_t) m_ttl << "std::endl";
+ os << " hop count = " << (uint16_t) m_hopCount << "std::endl";
+ os << " metric = " << m_metric << "std::endl";
+ os << " seqno = " << m_originatorSeqNumber << "std::endl";
+ os << " lifetime = " << m_lifetime << "std::endl";
+ os << " preq ID = " << m_preqId << "std::endl";
+ os << " Destinations are:std::endl";
+ for (int j = 0; j < m_destCount; j++)
+ {
+ os << " " << m_destinations[j]->GetDestinationAddress () << "std::endl";
+ }
+ os << "</information_element>" << std::endl;
+}
+std::vector<Ptr<DestinationAddressUnit> >
+IePreq::GetDestinationList ()
+{
+ return m_destinations;
+}
+void
+IePreq::AddDestinationAddressElement (bool doFlag, bool rfFlag, Mac48Address dest_address,
+ uint32_t dest_seq_number)
+{
+ for (std::vector<Ptr<DestinationAddressUnit> >::const_iterator i = m_destinations.begin (); i
+ != m_destinations.end (); i++)
+ {
+ if ((*i)->GetDestinationAddress () == dest_address)
+ {
+ return;
+ }
+ }
+ //TODO: check overflow
+ Ptr<DestinationAddressUnit> new_element = Create<DestinationAddressUnit> ();
+ new_element->SetFlags (doFlag, rfFlag, (dest_seq_number == 0));
+ new_element->SetDestinationAddress (dest_address);
+ new_element->SetDestSeqNumber (dest_seq_number);
+ m_destinations.push_back (new_element);
+ m_destCount++;
+}
+void
+IePreq::DelDestinationAddressElement (Mac48Address dest_address)
+{
+ for (std::vector<Ptr<DestinationAddressUnit> >::iterator i = m_destinations.begin (); i
+ != m_destinations.end (); i++)
+ {
+ if ((*i)->GetDestinationAddress () == dest_address)
+ {
+ m_destinations.erase (i);
+ m_destCount--;
+ break;
+ }
+ }
+}
+void
+IePreq::ClearDestinationAddressElements ()
+{
+ int i;
+ for (std::vector<Ptr<DestinationAddressUnit> >::iterator j = m_destinations.begin (); j
+ != m_destinations.end (); j++)
+ {
+ (*j) = 0;
+ }
+ for (i = 0; i < m_destCount; i++)
+ {
+ m_destinations.pop_back ();
+ }
+ m_destinations.clear ();
+ m_destCount = 0;
+}
+bool
+operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b)
+{
+ return (a.m_do == b.m_do && a.m_rf == b.m_rf && a.m_usn == b.m_usn && a.m_destinationAddress
+ == b.m_destinationAddress && a.m_destSeqNumber == b.m_destSeqNumber);
+}
+bool
+operator== (const IePreq & a, const IePreq & b)
+{
+ bool ok = (a.m_flags == b.m_flags && a.m_hopCount == b.m_hopCount && a.m_ttl == b.m_ttl && a.m_preqId
+ == b.m_preqId && a.m_originatorAddress == b.m_originatorAddress && a.m_originatorSeqNumber
+ == b.m_originatorSeqNumber && a.m_lifetime == b.m_lifetime && a.m_metric == b.m_metric && a.m_destCount
+ == b.m_destCount);
+
+ if (!ok)
+ {
+ return false;
+ }
+ if (a.m_destinations.size () != b.m_destinations.size ())
+ {
+ return false;
+ }
+ for (size_t i = 0; i < a.m_destinations.size (); ++i)
+ {
+ if (!(*(PeekPointer (a.m_destinations[i])) == *(PeekPointer (b.m_destinations[i]))))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+bool
+IePreq::MayAddAddress (Mac48Address originator)
+{
+ if (m_originatorAddress != originator)
+ {
+ return false;
+ }
+ if (m_destinations[0]->GetDestinationAddress () == Mac48Address::GetBroadcast ())
+ {
+ return false;
+ }
+ if ((GetInformationSize () + 11) > 255)
+ {
+ return false;
+ }
+ return true;
+}
+bool
+IePreq::IsFull () const
+{
+ return ((GetInformationSize () + 11) > 255);
+}
+std::ostream &
+operator << (std::ostream &os, const IePreq &a)
+{
+ a.Print (os);
+ return os;
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-preq.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,160 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef WIFI_PREQ_INFORMATION_ELEMENT_H
+#define WIFI_PREQ_INFORMATION_ELEMENT_H
+
+#include <vector>
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief Describes an address unit in PREQ information element
+ * See 7.3.2.96 for more details
+ */
+class DestinationAddressUnit : public RefCountBase
+{
+public:
+ DestinationAddressUnit ();
+ void SetFlags (bool doFlag, bool rfFlag, bool usnFlag);
+ void SetDestinationAddress (Mac48Address dest_address);
+ void SetDestSeqNumber (uint32_t dest_seq_number);
+ bool IsDo ();
+ bool IsRf ();
+ bool IsUsn ();
+ Mac48Address GetDestinationAddress () const;
+ uint32_t GetDestSeqNumber () const;
+private:
+ bool m_do;
+ bool m_rf;
+ bool m_usn;
+ Mac48Address m_destinationAddress;
+ uint32_t m_destSeqNumber;
+
+ friend bool operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b);
+};
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.96 of 802.11s draft 2.07
+ */
+class IePreq : public WifiInformationElement
+{
+public:
+ IePreq ();
+ ~IePreq ();
+ /**
+ * Add a destination address unit: flags, destination and sequence
+ * number
+ */
+ void AddDestinationAddressElement (
+ bool doFlag,
+ bool rfFlag,
+ Mac48Address dest_address,
+ uint32_t dest_seq_number
+ );
+ /// Delete a destination address unit by destination
+ void DelDestinationAddressElement (Mac48Address dest_address);
+ /// Clear PREQ: remove all destinations
+ void ClearDestinationAddressElements ();
+ /// Get all destinations, which are stored in PREQ:
+ std::vector<Ptr<DestinationAddressUnit> > GetDestinationList ();
+ /// SetProper flags which indicate that PREQ is unicast
+ void SetUnicastPreq ();
+ /*
+ * \brief In proactive case: need we send PREP
+ */
+ void SetNeedNotPrep ();
+ ///\name Setters for fields:
+ ///\{
+ void SetHopcount (uint8_t hopcount);
+ void SetTTL (uint8_t ttl);
+ void SetPreqID (uint32_t id);
+ void SetOriginatorAddress (Mac48Address originator_address);
+ void SetOriginatorSeqNumber (uint32_t originator_seq_number);
+ void SetLifetime (uint32_t lifetime);
+ void SetMetric (uint32_t metric);
+ void SetDestCount (uint8_t dest_count);
+ ///\}
+ ///\name Getters for fields:
+ ///\{
+ bool IsUnicastPreq () const;
+ bool IsNeedNotPrep () const;
+ uint8_t GetHopCount () const;
+ uint8_t GetTtl ()const ;
+ uint32_t GetPreqID () const;
+ Mac48Address GetOriginatorAddress () const;
+ uint32_t GetOriginatorSeqNumber () const;
+ uint32_t GetLifetime () const;
+ uint32_t GetMetric () const;
+ uint8_t GetDestCount () const;
+ ///\}
+ /// Handle TTL and Metric:
+ void DecrementTtl ();
+ void IncrementMetric (uint32_t metric);
+ /*
+ * \brief Checks that preq's originator address equals to originator, and
+ * this preq is not proactive
+ */
+ bool MayAddAddress (Mac48Address originator);
+ bool IsFull () const;
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator i, uint8_t length);
+ virtual uint8_t GetInformationSize () const;
+ virtual void Print (std::ostream& os) const;
+ ///\}
+private:
+ /**
+ * how many destinations we support
+ */
+ uint8_t m_maxSize; //TODO: make as an attrubute
+ /**
+ * Fields of information element:
+ */
+ uint8_t m_flags;
+ uint8_t m_hopCount;
+ uint8_t m_ttl;
+ uint32_t m_preqId;
+ Mac48Address m_originatorAddress;
+ uint32_t m_originatorSeqNumber;
+ uint32_t m_lifetime;
+ uint32_t m_metric;
+ uint8_t m_destCount;
+ std::vector<Ptr<DestinationAddressUnit> > m_destinations;
+
+ friend bool operator== (const IePreq & a, const IePreq & b);
+};
+
+bool operator== (const DestinationAddressUnit & a, const DestinationAddressUnit & b);
+bool operator== (const IePreq & a, const IePreq & b);
+std::ostream &operator << (std::ostream &os, const IePreq &preq);
+
+} // namespace dot11s
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-rann.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,180 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-rann.h"
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dot11s {
+
+IeRann::~IeRann ()
+{
+}
+IeRann::IeRann () :
+ m_flags (0), m_hopcount (0), m_ttl (0), m_originatorAddress (Mac48Address::GetBroadcast ()),
+ m_destSeqNumber (0), m_metric (0)
+{
+}
+WifiElementId
+IeRann::ElementId () const
+{
+ return IE11S_RANN;
+}
+
+void
+IeRann::SetFlags (uint8_t flags)
+{
+ m_flags = flags;
+}
+void
+IeRann::SetHopcount (uint8_t hopcount)
+{
+ m_hopcount = hopcount;
+}
+void
+IeRann::SetTTL (uint8_t ttl)
+{
+ m_ttl = ttl;
+}
+void
+IeRann::SetDestSeqNumber (uint32_t dest_seq_number)
+{
+ m_destSeqNumber = dest_seq_number;
+}
+void
+IeRann::SetMetric (uint32_t metric)
+{
+ m_metric = metric;
+}
+void
+IeRann::SetOriginatorAddress (Mac48Address originator_address)
+{
+ m_originatorAddress = originator_address;
+}
+
+uint8_t
+IeRann::GetFlags ()
+{
+ return m_flags;
+}
+uint8_t
+IeRann::GetHopcount ()
+{
+ return m_hopcount;
+}
+uint8_t
+IeRann::GetTtl ()
+{
+ return m_ttl;
+}
+uint32_t
+IeRann::GetDestSeqNumber ()
+{
+ return m_destSeqNumber;
+}
+uint32_t
+IeRann::GetMetric ()
+{
+ return m_metric;
+}
+void
+IeRann::DecrementTtl ()
+{
+ m_ttl--;
+ m_hopcount++;
+}
+
+void
+IeRann::IncrementMetric (uint32_t m)
+{
+ m_metric += m;
+}
+
+Mac48Address
+IeRann::GetOriginatorAddress ()
+{
+ return m_originatorAddress;
+}
+void
+IeRann::SerializeInformation (Buffer::Iterator i) const
+{
+ i.WriteU8 (m_flags);
+ i.WriteU8 (m_hopcount);
+ i.WriteU8 (m_ttl);
+ WriteTo (i, m_originatorAddress);
+ i.WriteHtolsbU32 (m_destSeqNumber);
+ i.WriteHtolsbU32 (m_metric);
+}
+uint8_t
+IeRann::DeserializeInformation (Buffer::Iterator start, uint8_t length)
+{
+ Buffer::Iterator i = start;
+ m_flags = i.ReadU8 ();
+ m_hopcount = i.ReadU8 ();
+ m_ttl = i.ReadU8 ();
+ ReadFrom (i, m_originatorAddress);
+ m_destSeqNumber = i.ReadLsbtohU32 ();
+ m_metric = i.ReadLsbtohU32 ();
+ return i.GetDistanceFrom (start);
+}
+uint8_t
+IeRann::GetInformationSize () const
+{
+ uint8_t retval = 1 //Flags
+ + 1 //Hopcount
+ + 1 //TTL
+ + 6 //OriginatorAddress
+ + 4 //DestSeqNumber
+ + 4;//Metric
+ return retval;
+}
+
+void
+IeRann::Print (std::ostream &os) const
+{
+ os << std::endl << "<information_element id=" << ElementId () << ">" << std::endl;
+ os << " flags = " << (int) m_flags << "std::endl";
+ os << " hop count = " << (int) m_hopcount << "std::endl";
+ os << " TTL = " << (int) m_ttl << "std::endl";
+ os << " originator address = " << m_originatorAddress << "std::endl";
+ os << " dst seq. number = " << m_destSeqNumber << "std::endl";
+ os << " metric = " << m_metric << "std::endl";
+ os << "</information_element>" << std::endl;
+}
+
+bool
+operator== (const IeRann & a, const IeRann & b)
+{
+ return (a.m_flags == b.m_flags && a.m_hopcount == b.m_hopcount && a.m_ttl == b.m_ttl
+ && a.m_originatorAddress == b.m_originatorAddress && a.m_destSeqNumber == b.m_destSeqNumber
+ && a.m_metric == b.m_metric);
+}
+std::ostream &
+operator << (std::ostream &os, const IeRann &a)
+{
+ a.Print (os);
+ return os;
+}
+}
+} // namespace ns3::dot11s
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/ie-dot11s-rann.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef RANN_INFORMATION_ELEMENT_H
+#define RANN_INFORMATION_ELEMENT_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/wifi-information-element-vector.h"
+
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ * \brief See 7.3.2.95 of 802.11s draft 2.07
+ */
+class IeRann : public WifiInformationElement
+{
+public:
+ IeRann ();
+ virtual ~IeRann ();
+ void SetFlags (uint8_t flags);
+ void SetHopcount (uint8_t hopcount);
+ void SetTTL (uint8_t ttl);
+ void SetOriginatorAddress (Mac48Address originator_address);
+ void SetDestSeqNumber (uint32_t dest_seq_number);
+ void SetMetric (uint32_t metric);
+ uint8_t GetFlags ();
+ uint8_t GetHopcount ();
+ uint8_t GetTtl ();
+ Mac48Address GetOriginatorAddress ();
+ uint32_t GetDestSeqNumber ();
+ uint32_t GetMetric ();
+ void DecrementTtl ();
+ void IncrementMetric (uint32_t metric);
+ /**
+ * \name Inherited from WifiInformationElement
+ * \{
+ */
+ virtual WifiElementId ElementId () const;
+ virtual void SerializeInformation (Buffer::Iterator i) const;
+ virtual uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length);
+ virtual uint8_t GetInformationSize () const;
+ virtual void Print (std::ostream &os) const;
+ ///\}
+private:
+ uint8_t m_flags;
+ uint8_t m_hopcount;
+ uint8_t m_ttl;
+ Mac48Address m_originatorAddress;
+ uint32_t m_destSeqNumber;
+ uint32_t m_metric;
+
+ friend bool operator== (const IeRann & a, const IeRann & b);
+};
+
+bool operator== (const IeRann & a, const IeRann & b);
+std::ostream &operator << (std::ostream &os, const IeRann &rann);
+} // namespace dot11s
+} //namespace ns3
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link-frame.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,311 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "peer-link-frame.h"
+#include "ie-dot11s-peer-management.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dot11s {
+NS_OBJECT_ENSURE_REGISTERED (PeerLinkFrameStart);
+
+PeerLinkFrameStart::PeerLinkFrameStart () :
+ m_subtype (255), m_capability (0), m_aid (0), m_rates (SupportedRates ()), m_meshId (IeMeshId ()),
+ m_config (IeConfiguration ()), m_reasonCode ((uint16_t) REASON11S_RESERVED)
+{
+}
+void
+PeerLinkFrameStart::SetPlinkFrameSubtype (uint8_t subtype)
+{
+ m_subtype = subtype;
+}
+void
+PeerLinkFrameStart::SetPlinkFrameStart (PeerLinkFrameStart::PlinkFrameStartFields fields)
+{
+ m_subtype = fields.subtype;
+ m_protocol = fields.protocol;
+ if (m_subtype != (uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE))
+ {
+ m_capability = fields.capability;
+ }
+ if (m_subtype == (uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM))
+ {
+ m_aid = fields.aid;
+ }
+ if (m_subtype != (uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE))
+ {
+ m_rates = fields.rates;
+ }
+ if (m_subtype != (uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM))
+ {
+ m_meshId = fields.meshId;
+ }
+ if (m_subtype != (uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE))
+ {
+ m_config = fields.config;
+ }
+ else
+ {
+ m_reasonCode = fields.reasonCode;
+ }
+}
+PeerLinkFrameStart::PlinkFrameStartFields
+PeerLinkFrameStart::GetFields ()
+{
+ PlinkFrameStartFields retval;
+ //TODO: protocol version:
+ retval.subtype = m_subtype;
+ retval.capability = m_capability;
+ retval.aid = m_aid;
+ retval.rates = m_rates;
+ retval.meshId = m_meshId;
+ retval.config = m_config;
+ retval.reasonCode = m_reasonCode;
+ return retval;
+}
+TypeId
+PeerLinkFrameStart::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::PeerLinkFrameStart") .SetParent<Header> () .AddConstructor<
+ PeerLinkFrameStart> ();
+ return tid;
+}
+TypeId
+PeerLinkFrameStart::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+void
+PeerLinkFrameStart::Print (std::ostream &os) const
+{
+ os << "subtype = " << (uint16_t) m_subtype << std::endl << "capability = " << m_capability << std::endl << "laid = "
+ << (uint16_t) m_aid << std::endl << "rates = " << m_rates << std::endl << "meshId = ";
+ m_meshId.Print (os);
+ os << std::endl << "configuration = ";
+ m_config.Print (os);
+ os << std::endl << "reason code = " << m_reasonCode;
+}
+uint32_t
+PeerLinkFrameStart::GetSerializedSize () const
+{
+ uint32_t size = 3; //Peering protocol
+ NS_ASSERT (m_subtype < 3);
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ size += 2; //capability
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM) == m_subtype)
+ {
+ size += 2; //AID of remote peer
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ size += m_rates.GetSerializedSize ();
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM) != m_subtype)
+ {
+ size += m_meshId.GetInformationSize () + 2;
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ size += m_config.GetInformationSize () + 2;
+ }
+ else
+ {
+ size += 2; //reasonCode
+ }
+ return size;
+}
+void
+PeerLinkFrameStart::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ NS_ASSERT (m_subtype < 3);
+ i.WriteU8 (IE11S_MESH_PEERING_PROTOCOL_VERSION);
+ i.WriteU8 (m_protocol.GetInformationSize ());
+ m_protocol.SerializeInformation (i);
+ i.Next (m_protocol.GetInformationSize ());
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ i.WriteHtolsbU16 (m_capability);
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM) == m_subtype)
+ {
+ i.WriteHtolsbU16 (m_aid);
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ i = m_rates.Serialize (i);
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM) != m_subtype)
+ {
+ i.WriteU8 (IE11S_MESH_ID);
+ i.WriteU8 (m_meshId.GetInformationSize ());
+ m_meshId.SerializeInformation (i);
+ i.Next (m_meshId.GetInformationSize ());
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ i.WriteU8 (IE11S_MESH_CONFIGURATION);
+ i.WriteU8 (m_config.GetInformationSize ());
+ m_config.SerializeInformation (i);
+ i.Next (m_config.GetInformationSize ());
+ }
+ else
+ {
+ i.WriteHtolsbU16 (m_reasonCode);
+ }
+}
+uint32_t
+PeerLinkFrameStart::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ NS_ASSERT (m_subtype < 3);
+ {
+ uint8_t id = i.ReadU8 ();
+ uint8_t length = i.ReadU8 ();
+ m_protocol.DeserializeInformation (i, length);
+ if ((m_protocol.ElementId () != (WifiElementId) id) || (m_protocol.GetInformationSize () != length))
+ {
+ NS_FATAL_ERROR ("Broken frame: Element ID does not match IE itself!");
+ }
+ i.Next (m_protocol.GetInformationSize ());
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ m_capability = i.ReadLsbtohU16 ();
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM) == m_subtype)
+ {
+ m_aid = i.ReadLsbtohU16 ();
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ i = m_rates.Deserialize (i);
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM) != m_subtype)
+ {
+ uint8_t id = i.ReadU8 ();
+ uint8_t length = i.ReadU8 ();
+ m_meshId.DeserializeInformation (i, length);
+ if ((m_meshId.ElementId () != (WifiElementId) id) || (m_meshId.GetInformationSize () != length))
+ {
+ NS_FATAL_ERROR ("Broken frame: Element ID does not match IE itself!");
+ }
+ i.Next (m_meshId.GetInformationSize ());
+ }
+ if ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE) != m_subtype)
+ {
+ uint8_t id = i.ReadU8 ();
+ uint8_t length = i.ReadU8 ();
+ m_config. DeserializeInformation (i, length);
+ if ((m_config.ElementId () != (WifiElementId) id) || (m_config.GetInformationSize () != length))
+ {
+ NS_FATAL_ERROR ("Broken frame: Element ID does not match IE itself!");
+ }
+ i.Next (m_config.GetInformationSize ());
+ }
+ else
+ {
+ m_reasonCode = i.ReadLsbtohU16 ();
+ }
+ return i.GetDistanceFrom (start);
+}
+bool
+operator== (const PeerLinkFrameStart & a, const PeerLinkFrameStart & b)
+{
+ return ((a.m_subtype == b.m_subtype) && (a.m_capability == b.m_capability) && (a.m_aid == b.m_aid)
+ && (a.m_meshId.IsEqual (b.m_meshId)) && (a.m_config == b.m_config)
+ && (a.m_reasonCode == b.m_reasonCode));
+}
+#ifdef RUN_SELF_TESTS
+/// Built-in self test for PeerLinkFrameStart
+struct PeerLinkFrameStartBist : public Test
+{
+ PeerLinkFrameStartBist () :
+ Test ("Mesh/802.11s/PeerLinkFrameStart")
+ {
+ }
+ virtual bool
+ RunTests ();
+};
+/// Test instance
+static PeerLinkFrameStartBist g_PeerLinkFrameStartBist;
+
+bool
+PeerLinkFrameStartBist::RunTests ()
+{
+ bool result (true);
+ {
+ PeerLinkFrameStart a;
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.subtype = (uint8_t) (WifiMeshActionHeader::PEER_LINK_OPEN);
+ fields.capability = 0;
+ fields.aid = 101;
+ fields.reasonCode = 12;
+ fields.meshId = IeMeshId ("qwertyuiop");
+ a.SetPlinkFrameStart (fields);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ PeerLinkFrameStart b;
+ b.SetPlinkFrameSubtype ((uint8_t) (WifiMeshActionHeader::PEER_LINK_OPEN));
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ PeerLinkFrameStart a;
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.subtype = (uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM);
+ fields.capability = 0;
+ fields.aid = 1234;
+ fields.reasonCode = 12;
+ fields.meshId = IeMeshId ("qwerty");
+ a.SetPlinkFrameStart (fields);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ PeerLinkFrameStart b;
+ b.SetPlinkFrameSubtype ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CONFIRM));
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ {
+ PeerLinkFrameStart a;
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.subtype = (uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE);
+ fields.capability = 0;
+ fields.aid = 10;
+ fields.meshId = IeMeshId ("qqq");
+ fields.reasonCode = 12;
+ a.SetPlinkFrameStart (fields);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ PeerLinkFrameStart b;
+ b.SetPlinkFrameSubtype ((uint8_t) (WifiMeshActionHeader::PEER_LINK_CLOSE));
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (a, b);
+ }
+ return result;
+}
+#endif
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link-frame.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,93 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef PEER_LINK_FRAME_START_H
+#define PEER_LINK_FRAME_START_H
+#include "ns3/header.h"
+#include "ns3/supported-rates.h"
+#include "dot11s-mac-header.h"
+#include "ie-dot11s-configuration.h"
+#include "ie-dot11s-peering-protocol.h"
+#include "ie-dot11s-id.h"
+namespace ns3
+{
+class MeshWifiInterfaceMac;
+namespace dot11s
+{
+/**
+ * \ingroup dot11s
+ *
+ * \brief 802.11s Peer link management frame:
+ * \details included the following (see chapters 7.4.12.1-7.4.12.3 of
+ * 802.11s):
+ * - Subtype field
+ * - Association ID field
+ * - Supported rates
+ * - Mesh ID of mesh
+ */
+class PeerLinkFrameStart : public Header
+{
+public:
+ PeerLinkFrameStart ();
+ ///\brief fields:
+ struct PlinkFrameStartFields
+ {
+ uint8_t subtype;
+ IePeeringProtocol protocol; //Peering protocol version - in all subtypes - 3 octets
+ uint16_t capability; //open and confirm
+ uint16_t aid; //confirm only
+ SupportedRates rates; //open and confirm
+ IeMeshId meshId; //open and close
+ IeConfiguration config; //open and confirm
+ uint16_t reasonCode; //close only
+ };
+ ///\attention: must be set before deserialize, before only multihop
+ //action header knows about subtype
+ void SetPlinkFrameSubtype (uint8_t subtype);
+ void SetPlinkFrameStart (PlinkFrameStartFields);
+ PlinkFrameStartFields GetFields ();
+ /** \name Inherited from header:
+ * \{
+ */
+ static TypeId GetTypeId ();
+ virtual TypeId GetInstanceTypeId () const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+ /**
+ * \}
+ */
+private:
+ uint8_t m_subtype;
+ IePeeringProtocol m_protocol;
+ uint16_t m_capability;
+ uint16_t m_aid;
+ SupportedRates m_rates;
+ IeMeshId m_meshId;
+ IeConfiguration m_config;
+ uint16_t m_reasonCode;
+
+ friend bool operator== (const PeerLinkFrameStart & a, const PeerLinkFrameStart & b);
+};
+bool operator== (const PeerLinkFrameStart & a, const PeerLinkFrameStart & b);
+} //namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,692 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "peer-link.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/traced-value.h"
+
+NS_LOG_COMPONENT_DEFINE ("Dot11sPeerManagementProtocol");
+
+namespace ns3 {
+namespace dot11s {
+
+NS_OBJECT_ENSURE_REGISTERED( PeerLink);
+
+TypeId
+PeerLink::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::dot11s::PeerLink")
+ .SetParent<Object> ()
+ .AddConstructor<PeerLink> ()
+ .AddAttribute ( "RetryTimeout",
+ "Retry timeout",
+ TimeValue (TimeValue (MicroSeconds (40 * 1024))),
+ MakeTimeAccessor (
+ &PeerLink::m_dot11MeshRetryTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "HoldingTimeout",
+ "Holding timeout",
+ TimeValue (TimeValue (MicroSeconds (40 * 1024))),
+ MakeTimeAccessor (
+ &PeerLink::m_dot11MeshHoldingTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "ConfirmTimeout",
+ "Confirm timeout",
+ TimeValue (TimeValue (MicroSeconds (40 * 1024))),
+ MakeTimeAccessor (
+ &PeerLink::m_dot11MeshConfirmTimeout),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "MaxRetries",
+ "Maximum number of retries",
+ UintegerValue (4),
+ MakeUintegerAccessor (
+ &PeerLink::m_dot11MeshMaxRetries),
+ MakeUintegerChecker<uint16_t> ()
+ )
+ .AddAttribute ( "MaxBeaconLoss",
+ "Maximum number of lost beacons before link will be closed",
+ UintegerValue (2),
+ MakeUintegerAccessor (
+ &PeerLink::m_maxBeaconLoss),
+ MakeUintegerChecker<uint16_t> (1)
+ )
+ .AddAttribute ( "MaxPacketFailure",
+ "Maximum number of failed packets before link will be closed",
+ UintegerValue (2),
+ MakeUintegerAccessor (
+ &PeerLink::m_maxPacketFail),
+ MakeUintegerChecker<uint16_t> (1)
+ )
+ ;
+ return tid;
+}
+
+
+//-----------------------------------------------------------------------------
+// PeerLink public interface
+//-----------------------------------------------------------------------------
+PeerLink::PeerLink () :
+ m_peerAddress (Mac48Address::GetBroadcast ()), m_peerMeshPointAddress (Mac48Address::GetBroadcast ()),
+ m_localLinkId (0), m_peerLinkId (0), m_packetFail (0), m_state (IDLE), m_retryCounter (0), m_maxPacketFail (3)
+{
+}
+PeerLink::~PeerLink ()
+{
+}
+void
+PeerLink::DoDispose ()
+{
+ m_retryTimer.Cancel ();
+ m_holdingTimer.Cancel ();
+ m_confirmTimer.Cancel ();
+ m_beaconLossTimer.Cancel ();
+ m_beaconTiming.ClearTimingElement ();
+}
+void
+PeerLink::SetPeerAddress (Mac48Address macaddr)
+{
+ m_peerAddress = macaddr;
+}
+void
+PeerLink::SetPeerMeshPointAddress (Mac48Address macaddr)
+{
+ m_peerMeshPointAddress = macaddr;
+}
+void
+PeerLink::SetInterface (uint32_t interface)
+{
+ m_interface = interface;
+}
+void
+PeerLink::SetLocalLinkId (uint16_t id)
+{
+ m_localLinkId = id;
+}
+void
+PeerLink::SetLocalAid (uint16_t aid)
+{
+ m_assocId = aid;
+}
+void
+PeerLink::SetBeaconInformation (Time lastBeacon, Time beaconInterval)
+{
+ m_lastBeacon = lastBeacon;
+ m_beaconInterval = beaconInterval;
+ m_beaconLossTimer.Cancel ();
+ Time delay = Seconds (beaconInterval.GetSeconds () * m_maxBeaconLoss);
+ NS_ASSERT (delay.GetMicroSeconds () != 0);
+ m_beaconLossTimer = Simulator::Schedule (delay, &PeerLink::BeaconLoss, this);
+}
+void
+PeerLink::MLMESetSignalStatusCallback (PeerLink::SignalStatusCallback cb)
+{
+ m_linkStatusCallback = cb;
+}
+void
+PeerLink::BeaconLoss ()
+{
+ StateMachine (CNCL);
+}
+void
+PeerLink::TransmissionSuccess ()
+{
+ m_packetFail = 0;
+}
+void
+PeerLink::TransmissionFailure ()
+{
+ m_packetFail ++;
+ if (m_packetFail == m_maxPacketFail)
+ {
+ StateMachine (CNCL);
+ m_packetFail = 0;
+ }
+}
+
+void
+PeerLink::SetBeaconTimingElement (IeBeaconTiming beaconTiming)
+{
+ m_beaconTiming = beaconTiming;
+}
+Mac48Address
+PeerLink::GetPeerAddress () const
+{
+ return m_peerAddress;
+}
+uint16_t
+PeerLink::GetLocalAid () const
+{
+ return m_assocId;
+}
+Time
+PeerLink::GetLastBeacon () const
+{
+ return m_lastBeacon;
+}
+Time
+PeerLink::GetBeaconInterval () const
+{
+ return m_beaconInterval;
+}
+IeBeaconTiming
+PeerLink::GetBeaconTimingElement () const
+{
+ return m_beaconTiming;
+}
+void
+PeerLink::MLMECancelPeerLink (PmpReasonCode reason)
+{
+ StateMachine (CNCL, reason);
+}
+void
+PeerLink::MLMEActivePeerLinkOpen ()
+{
+ StateMachine (ACTOPN);
+}
+void
+PeerLink::MLMEPeeringRequestReject ()
+{
+ StateMachine (REQ_RJCT, REASON11S_PEERING_CANCELLED);
+}
+void
+PeerLink::Close (uint16_t localLinkId, uint16_t peerLinkId, PmpReasonCode reason)
+{
+ if (peerLinkId != 0 && m_localLinkId != peerLinkId)
+ {
+ return;
+ }
+ if (m_peerLinkId == 0)
+ {
+ m_peerLinkId = localLinkId;
+ }
+ else
+ {
+ if (m_peerLinkId != localLinkId)
+ {
+ return;
+ }
+ }
+ StateMachine (CLS_ACPT, reason);
+}
+void
+PeerLink::OpenAccept (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp)
+{
+ if (m_peerLinkId == 0)
+ {
+ m_peerLinkId = localLinkId;
+ }
+ m_configuration = conf;
+ if (m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT (m_peerMeshPointAddress == peerMp);
+ }
+ else
+ {
+ m_peerMeshPointAddress = peerMp;
+ }
+ StateMachine (OPN_ACPT);
+}
+void
+PeerLink::OpenReject (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp, PmpReasonCode reason)
+{
+ if (m_peerLinkId == 0)
+ {
+ m_peerLinkId = localLinkId;
+ }
+ m_configuration = conf;
+ if (m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT (m_peerMeshPointAddress == peerMp);
+ }
+ else
+ {
+ m_peerMeshPointAddress = peerMp;
+ }
+ StateMachine (OPN_RJCT, reason);
+}
+void
+PeerLink::ConfirmAccept (uint16_t localLinkId, uint16_t peerLinkId, uint16_t peerAid, IeConfiguration conf,
+ Mac48Address peerMp)
+{
+ if (m_localLinkId != peerLinkId)
+ {
+ return;
+ }
+ if (m_peerLinkId == 0)
+ {
+ m_peerLinkId = localLinkId;
+ }
+ else
+ {
+ if (m_peerLinkId != localLinkId)
+ {
+ return;
+ }
+ }
+ m_configuration = conf;
+ m_peerAssocId = peerAid;
+ if (m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT (m_peerMeshPointAddress == peerMp);
+ }
+ else
+ {
+ m_peerMeshPointAddress = peerMp;
+ }
+ StateMachine (CNF_ACPT);
+}
+void
+PeerLink::ConfirmReject (uint16_t localLinkId, uint16_t peerLinkId, IeConfiguration conf,
+ Mac48Address peerMp, PmpReasonCode reason)
+{
+ if (m_localLinkId != peerLinkId)
+ {
+ return;
+ }
+ if (m_peerLinkId == 0)
+ {
+ m_peerLinkId = localLinkId;
+ }
+ else
+ {
+ if (m_peerLinkId != localLinkId)
+ {
+ return;
+ }
+ }
+ m_configuration = conf;
+ if (m_peerMeshPointAddress != Mac48Address::GetBroadcast ())
+ {
+ NS_ASSERT (m_peerMeshPointAddress == peerMp);
+ }
+ m_peerMeshPointAddress = peerMp;
+ StateMachine (CNF_RJCT, reason);
+}
+bool
+PeerLink::LinkIsEstab () const
+{
+ return (m_state == ESTAB);
+}
+bool
+PeerLink::LinkIsIdle () const
+{
+ return (m_state == IDLE);
+}
+void
+PeerLink::SetMacPlugin (Ptr<PeerManagementProtocolMac> plugin)
+{
+ m_macPlugin = plugin;
+}
+//-----------------------------------------------------------------------------
+// Private
+//-----------------------------------------------------------------------------
+void
+PeerLink::StateMachine (PeerEvent event, PmpReasonCode reasoncode)
+{
+ switch (m_state)
+ {
+ case IDLE:
+ switch (event)
+ {
+ case CNCL:
+ case CLS_ACPT:
+ m_state = IDLE;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, IDLE, IDLE);
+ break;
+ case REQ_RJCT:
+ SendPeerLinkClose (reasoncode);
+ break;
+ case ACTOPN:
+ m_state = OPN_SNT;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, IDLE, OPN_SNT);
+ SendPeerLinkOpen ();
+ SetRetryTimer ();
+ break;
+ case OPN_ACPT:
+ m_state = OPN_RCVD;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, IDLE, OPN_RCVD);
+ SendPeerLinkConfirm ();
+ SendPeerLinkOpen ();
+ SetRetryTimer ();
+ break;
+ default:
+ //11B.5.3.4 of 802.11s Draft D3.0
+ //All other events shall be ignored in this state
+ break;
+ }
+ break;
+ case OPN_SNT:
+ switch (event)
+ {
+ case TOR1:
+ SendPeerLinkOpen ();
+ m_retryCounter++;
+ SetRetryTimer ();
+ break;
+ case CNF_ACPT:
+ m_state = CNF_RCVD;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_SNT, CNF_RCVD);
+ ClearRetryTimer ();
+ SetConfirmTimer ();
+ break;
+ case OPN_ACPT:
+ m_state = OPN_RCVD;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_SNT, OPN_RCVD);
+ SendPeerLinkConfirm ();
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_SNT, HOLDING);
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_SNT, HOLDING);
+ ClearRetryTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case TOR2:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_SNT, HOLDING);
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_MAX_RETRIES);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_SNT, HOLDING);
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ default:
+ //11B.5.3.5 of 802.11s Draft D3.0
+ //All other events shall be ignored in this state
+ break;
+ }
+ break;
+ case CNF_RCVD:
+ switch (event)
+ {
+ case CNF_ACPT:
+ break;
+ case OPN_ACPT:
+ m_state = ESTAB;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, CNF_RCVD, ESTAB);
+ ClearConfirmTimer ();
+ SendPeerLinkConfirm ();
+ NS_ASSERT (m_peerMeshPointAddress != Mac48Address::GetBroadcast ());
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, CNF_RCVD, HOLDING);
+ ClearConfirmTimer ();
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case CNF_RJCT:
+ case OPN_RJCT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, CNF_RCVD, HOLDING);
+ ClearConfirmTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, CNF_RCVD, HOLDING);
+ ClearConfirmTimer ();
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ case TOC:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, CNF_RCVD, HOLDING);
+ SendPeerLinkClose (REASON11S_MESH_CONFIRM_TIMEOUT);
+ SetHoldingTimer ();
+ break;
+ default:
+ //11B.5.3.6 of 802.11s Draft D3.0
+ //All other events shall be ignored in this state
+ break;
+ }
+ break;
+ case OPN_RCVD:
+ switch (event)
+ {
+ case TOR1:
+ SendPeerLinkOpen ();
+ m_retryCounter++;
+ SetRetryTimer ();
+ break;
+ case CNF_ACPT:
+ m_state = ESTAB;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_RCVD, ESTAB);
+ ClearRetryTimer ();
+ NS_ASSERT (m_peerMeshPointAddress != Mac48Address::GetBroadcast ());
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_RCVD, HOLDING);
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_RCVD, HOLDING);
+ ClearRetryTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case TOR2:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_RCVD, HOLDING);
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_MESH_MAX_RETRIES);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, OPN_RCVD, HOLDING);
+ ClearRetryTimer ();
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ default:
+ //11B.5.3.7 of 802.11s Draft D3.0
+ //All other events shall be ignored in this state
+ break;
+ }
+ break;
+ case ESTAB:
+ switch (event)
+ {
+ case OPN_ACPT:
+ SendPeerLinkConfirm ();
+ break;
+ case CLS_ACPT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, ESTAB, HOLDING);
+ SendPeerLinkClose (REASON11S_MESH_CLOSE_RCVD);
+ SetHoldingTimer ();
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, ESTAB, HOLDING);
+ ClearRetryTimer ();
+ SendPeerLinkClose (reasoncode);
+ SetHoldingTimer ();
+ break;
+ case CNCL:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, ESTAB, HOLDING);
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ SetHoldingTimer ();
+ break;
+ default:
+ //11B.5.3.8 of 802.11s Draft D3.0
+ //All other events shall be ignored in this state
+ break;
+ }
+ break;
+ case HOLDING:
+ switch (event)
+ {
+ case CLS_ACPT:
+ ClearHoldingTimer ();
+ case TOH:
+ m_state = IDLE;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, HOLDING, IDLE);
+ break;
+ case OPN_ACPT:
+ case CNF_ACPT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, HOLDING, HOLDING);
+ // reason not spec in D2.0
+ SendPeerLinkClose (REASON11S_PEERING_CANCELLED);
+ break;
+ case OPN_RJCT:
+ case CNF_RJCT:
+ m_state = HOLDING;
+ m_linkStatusCallback (m_interface, m_peerAddress, m_peerMeshPointAddress, HOLDING, HOLDING);
+ SendPeerLinkClose (reasoncode);
+ break;
+ default:
+ //11B.5.3.9 of 802.11s Draft D3.0
+ //All other events shall be ignored in this state
+ break;
+ }
+ break;
+ }
+}
+void
+PeerLink::ClearRetryTimer ()
+{
+ m_retryTimer.Cancel ();
+}
+void
+PeerLink::ClearConfirmTimer ()
+{
+ m_confirmTimer.Cancel ();
+}
+void
+PeerLink::ClearHoldingTimer ()
+{
+ m_holdingTimer.Cancel ();
+}
+void
+PeerLink::SendPeerLinkClose (PmpReasonCode reasoncode)
+{
+ IePeerManagement peerElement;
+ peerElement.SetPeerClose (m_localLinkId, m_peerLinkId, reasoncode);
+ m_macPlugin->SendPeerLinkManagementFrame (m_peerAddress, m_peerMeshPointAddress, m_assocId, peerElement,
+ m_configuration);
+}
+void
+PeerLink::SendPeerLinkOpen ()
+{
+ IePeerManagement peerElement;
+ peerElement.SetPeerOpen (m_localLinkId);
+ NS_ASSERT (m_macPlugin != 0);
+ m_macPlugin->SendPeerLinkManagementFrame (m_peerAddress, m_peerMeshPointAddress, m_assocId, peerElement,
+ m_configuration);
+}
+void
+PeerLink::SendPeerLinkConfirm ()
+{
+ IePeerManagement peerElement;
+ peerElement.SetPeerConfirm (m_localLinkId, m_peerLinkId);
+ m_macPlugin->SendPeerLinkManagementFrame (m_peerAddress, m_peerMeshPointAddress, m_assocId, peerElement,
+ m_configuration);
+}
+void
+PeerLink::SetHoldingTimer ()
+{
+ NS_ASSERT (m_dot11MeshHoldingTimeout.GetMicroSeconds () != 0);
+ m_holdingTimer = Simulator::Schedule (m_dot11MeshHoldingTimeout, &PeerLink::HoldingTimeout, this);
+}
+void
+PeerLink::HoldingTimeout ()
+{
+ StateMachine (TOH);
+}
+void
+PeerLink::SetRetryTimer ()
+{
+ NS_ASSERT (m_dot11MeshRetryTimeout.GetMicroSeconds () != 0);
+ m_retryTimer = Simulator::Schedule (m_dot11MeshRetryTimeout, &PeerLink::RetryTimeout, this);
+}
+void
+PeerLink::RetryTimeout ()
+{
+ if (m_retryCounter < m_dot11MeshMaxRetries)
+ {
+ StateMachine (TOR1);
+ }
+ else
+ {
+ StateMachine (TOR2);
+ }
+}
+void
+PeerLink::SetConfirmTimer ()
+{
+ NS_ASSERT (m_dot11MeshConfirmTimeout.GetMicroSeconds () != 0);
+ m_confirmTimer = Simulator::Schedule (m_dot11MeshConfirmTimeout, &PeerLink::ConfirmTimeout, this);
+}
+void
+PeerLink::ConfirmTimeout ()
+{
+ StateMachine (TOC);
+}
+void
+PeerLink::Report (std::ostream & os) const
+{
+ if (m_state != ESTAB)
+ {
+ return;
+ }
+ os << "<PeerLink" << std::endl <<
+ "localAddress=\"" << m_macPlugin->GetAddress () << "\"" << std::endl <<
+ "peerInterfaceAddress=\"" << m_peerAddress << "\"" << std::endl <<
+ "peerMeshPointAddress=\"" << m_peerMeshPointAddress << "\"" << std::endl <<
+ "metric=\"" << m_macPlugin->GetLinkMetric (m_peerAddress) << "\"" << std::endl <<
+ "lastBeacon=\"" << m_lastBeacon.GetSeconds () << "\"" << std::endl <<
+ "localLinkId=\"" << m_localLinkId << "\"" << std::endl <<
+ "peerLinkId=\"" << m_peerLinkId << "\"" << std::endl <<
+ "assocId=\"" << m_assocId << "\"" << std::endl <<
+ "/>" << std::endl;
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-link.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,265 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+#ifndef PEERLLINK_H_
+#define PEERLLINK_H_
+
+#include "ns3/nstime.h"
+#include "ns3/callback.h"
+#include "ns3/mac48-address.h"
+#include "ns3/event-id.h"
+#include "ie-dot11s-beacon-timing.h"
+#include "ie-dot11s-peer-management.h"
+#include "ie-dot11s-configuration.h"
+#include "peer-management-protocol-mac.h"
+namespace ns3 {
+namespace dot11s {
+/**
+ * \ingroup dot11s
+ *
+ * \brief Peer link model for 802.11s Peer Management protocol
+ */
+class PeerLink : public Object
+{
+public:
+ friend class PeerManagementProtocol;
+ /// Support object system
+ static TypeId GetTypeId ();
+ /// C-tor create empty link
+ PeerLink ();
+ ~PeerLink ();
+ void DoDispose ();
+
+ /// Process beacon received from peer
+ void SetBeaconInformation (Time lastBeacon, Time BeaconInterval);
+ /**
+ * \brief Method used to detecet peer link changes
+ *
+ * \param bool if true - opened new link, if false - link closed
+ */
+ void SetLinkStatusCallback (Callback<void, uint32_t, Mac48Address, bool> cb);
+ /**
+ * \name Peer link geeters/setters
+ * \{
+ */
+ void SetPeerAddress (Mac48Address macaddr);
+ void SetPeerMeshPointAddress (Mac48Address macaddr);
+ void SetInterface (uint32_t interface);
+ void SetLocalLinkId (uint16_t id);
+ void SetPeerLinkId (uint16_t id);
+ void SetLocalAid (uint16_t aid);
+ void SetPeerAid (uint16_t aid);
+ void SetBeaconTimingElement (IeBeaconTiming beaconTiming);
+ void SetPeerLinkDescriptorElement (IePeerManagement peerLinkElement);
+ Mac48Address GetPeerAddress () const;
+ uint16_t GetLocalAid () const;
+ Time GetLastBeacon () const;
+ Time GetBeaconInterval () const;
+ IeBeaconTiming GetBeaconTimingElement ()const;
+ IePeerManagement GetPeerLinkDescriptorElement ()const;
+ //\}
+
+ /**
+ * \name MLME
+ * \{
+ */
+ /// MLME-CancelPeerLink.request
+ void MLMECancelPeerLink (PmpReasonCode reason);
+ /// MLME-ActivePeerLinkOpen.request
+ void MLMEActivePeerLinkOpen ();
+ /// MLME-PeeringRequestReject
+ void MLMEPeeringRequestReject ();
+ enum PeerState {
+ IDLE,
+ OPN_SNT,
+ CNF_RCVD,
+ OPN_RCVD,
+ ESTAB,
+ HOLDING,
+ };
+ /// Callback type for MLME-SignalPeerLinkStatus event
+ typedef Callback<void, uint32_t, Mac48Address, Mac48Address, PeerLink::PeerState, PeerLink::PeerState> SignalStatusCallback;
+ /// Set callback
+ void MLMESetSignalStatusCallback (SignalStatusCallback);
+ /// Reports about transmission success/failure
+ void TransmissionSuccess ();
+ void TransmissionFailure ();
+ //\}
+ ///\brief Statistics
+ void Report (std::ostream & os) const;
+private:
+ /**
+ * \name Link response to received management frames
+ *
+ * \attention In all this methods {local/peer}LinkID correspond to _peer_ station, as written in
+ * received frame, e.g. I am peerLinkID and peer link is localLinkID .
+ *
+ * \{
+ */
+ /// Close link
+ void Close (uint16_t localLinkID, uint16_t peerLinkID, PmpReasonCode reason);
+ /// Accept open link
+ void OpenAccept (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp);
+ /// Reject open link
+ void OpenReject (uint16_t localLinkId, IeConfiguration conf, Mac48Address peerMp, PmpReasonCode reason);
+ /// Confirm accept
+ void ConfirmAccept (
+ uint16_t localLinkId,
+ uint16_t peerLinkId,
+ uint16_t peerAid,
+ IeConfiguration conf,
+ Mac48Address peerMp
+ );
+ /// Confirm reject
+ void ConfirmReject (
+ uint16_t localLinkId,
+ uint16_t peerLinkId,
+ IeConfiguration conf,
+ Mac48Address peerMp,
+ PmpReasonCode reason
+ );
+ //\}
+
+ /// True if link is established
+ bool LinkIsEstab () const;
+ /// True if link is idle. Link can be deleted in this state
+ bool LinkIsIdle () const;
+ /**
+ * Set pointer to MAC-plugin, which is responsible for sending peer
+ * link management frames
+ */
+ void SetMacPlugin (Ptr<PeerManagementProtocolMac> plugin);
+ /// Peer link states, see 802.11s draft 11B.3.3.1
+private:
+ /// Peer link events, see 802.11s draft 11B.3.3.2
+ enum PeerEvent
+ {
+ CNCL, ///< Cancel peer link
+ ACTOPN, ///< Active peer link open
+ CLS_ACPT, ///< PeerLinkClose_Accept
+ OPN_ACPT, ///< PeerLinkOpen_Accept
+ OPN_RJCT, ///< PeerLinkOpen_Reject
+ REQ_RJCT, ///< PeerLinkOpenReject by internal reason
+ CNF_ACPT, ///< PeerLinkConfirm_Accept
+ CNF_RJCT, ///< PeerLinkConfirm_Reject
+ TOR1, ///< Timeout of retry timer
+ TOR2, ///< also timeout of retry timer
+ TOC, ///< Timeout of confirm timer
+ TOH, ///< Timeout of holding (gracefull closing) timer
+ };
+
+private:
+ /// State transition
+ void StateMachine (PeerEvent event, PmpReasonCode = REASON11S_RESERVED);
+
+ /**
+ * \name Event handlers
+ * \{
+ */
+ void ClearRetryTimer ();
+ void ClearConfirmTimer ();
+ void ClearHoldingTimer ();
+ void SetHoldingTimer ();
+ void SetRetryTimer ();
+ void SetConfirmTimer ();
+ //\}
+
+ /**
+ * \name Work with management frames
+ * \{
+ */
+ void SendPeerLinkClose (PmpReasonCode reasoncode);
+ void SendPeerLinkOpen ();
+ void SendPeerLinkConfirm ();
+ //\}
+
+ /**
+ * \name Timeout handlers
+ * \{
+ */
+ void HoldingTimeout ();
+ void RetryTimeout ();
+ void ConfirmTimeout ();
+ //\}
+
+private:
+ ///The number of interface I am associated with
+ uint32_t m_interface;
+ /// pointer to mac plugin, which is responsible for peer management
+ Ptr<PeerManagementProtocolMac> m_macPlugin;
+ /// Peer address
+ Mac48Address m_peerAddress;
+ /// Mesh point address, equal to peer address in case of single
+ //interface mesh point
+ Mac48Address m_peerMeshPointAddress;
+ /// My ID of this link
+ uint16_t m_localLinkId;
+ /// Peer ID of this link
+ uint16_t m_peerLinkId;
+ /// My association ID
+ uint16_t m_assocId;
+ /// Assoc Id assigned to me by peer
+ uint16_t m_peerAssocId;
+
+ /// When last beacon was received
+ Time m_lastBeacon;
+ /// Current beacon interval on corresponding interface
+ Time m_beaconInterval;
+ /// How many successive packets were failed to transmit
+ uint16_t m_packetFail;
+
+ /// Current state
+ PeerState m_state;
+ /// Mesh interface configuration
+ IeConfiguration m_configuration;
+
+ // State is a bitfield as defined as follows:
+ // This are states for a given
+ IeBeaconTiming m_beaconTiming;
+
+ /**
+ * \name Timers & counters used for internal state transitions
+ * \{
+ */
+ uint16_t m_dot11MeshMaxRetries;
+ Time m_dot11MeshRetryTimeout;
+ Time m_dot11MeshHoldingTimeout;
+ Time m_dot11MeshConfirmTimeout;
+
+ EventId m_retryTimer;
+ EventId m_holdingTimer;
+ EventId m_confirmTimer;
+ uint16_t m_retryCounter;
+ EventId m_beaconLossTimer;
+ uint16_t m_maxBeaconLoss;
+ uint16_t m_maxPacketFail;
+ //\}
+
+ /// Several successive beacons were lost, close link
+ void BeaconLoss ();
+
+ /// How to report my status change
+ SignalStatusCallback m_linkStatusCallback;
+};
+
+} // namespace dot11s
+} //namespace ns3
+#endif /* PEERLLINK_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-protocol-mac.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,332 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "ie-dot11s-configuration.h"
+#include "ie-dot11s-peer-management.h"
+#include "dot11s-mac-header.h"
+#include "peer-management-protocol-mac.h"
+#include "peer-management-protocol.h"
+#include "peer-link-frame.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/simulator.h"
+#include "ns3/wifi-mac-header.h"
+#include "ns3/wifi-information-element-vector.h"
+#include "ns3/log.h"
+namespace ns3 {
+namespace dot11s {
+PeerManagementProtocolMac::PeerManagementProtocolMac (uint32_t interface,
+ Ptr<PeerManagementProtocol> protocol)
+{
+ m_ifIndex = interface;
+ m_protocol = protocol;
+}
+
+PeerManagementProtocolMac::~PeerManagementProtocolMac ()
+{
+}
+
+void
+PeerManagementProtocolMac::SetParent (Ptr<MeshWifiInterfaceMac> parent)
+{
+ m_parent = parent;
+ m_parent->TraceConnectWithoutContext ("TxErrHeader", MakeCallback (&PeerManagementProtocolMac::TxError, this));
+ m_parent->TraceConnectWithoutContext ("TxOkHeader", MakeCallback (&PeerManagementProtocolMac::TxOk, this));
+}
+void
+PeerManagementProtocolMac::TxError (WifiMacHeader const &hdr)
+{
+ m_protocol->TransmissionFailure (m_ifIndex, hdr.GetAddr1 ());
+}
+void
+PeerManagementProtocolMac::TxOk (WifiMacHeader const &hdr)
+{
+ m_protocol->TransmissionSuccess (m_ifIndex, hdr.GetAddr1 ());
+}
+bool
+PeerManagementProtocolMac::Receive (Ptr<Packet> const_packet, const WifiMacHeader & header)
+{
+ // First of all we copy a packet, because we need to remove some
+ //headers
+ Ptr<Packet> packet = const_packet->Copy ();
+ if (header.IsBeacon ())
+ {
+ MgtBeaconHeader beacon_hdr;
+ packet->RemoveHeader (beacon_hdr);
+ //meshId.FindFirst (myBeacon);
+ bool meshBeacon = false;
+ WifiInformationElementVector elements;
+ packet->RemoveHeader(elements);
+ Ptr<IeBeaconTiming> beaconTiming = DynamicCast<IeBeaconTiming> (elements.FindFirst (IE11S_BEACON_TIMING));
+ Ptr<IeMeshId> meshId = DynamicCast<IeMeshId> (elements.FindFirst (IE11S_MESH_ID));
+
+ if ((beaconTiming != 0) && (meshId != 0))
+ {
+ if (m_protocol->GetMeshId ()->IsEqual (*meshId))
+ {
+ meshBeacon = true;
+ }
+ }
+ m_protocol->UpdatePeerBeaconTiming (m_ifIndex, meshBeacon, *beaconTiming, header.GetAddr2 (),
+ Simulator::Now (), MicroSeconds (beacon_hdr.GetBeaconIntervalUs ()));
+ // Beacon shall not be dropeed. May be needed to another plugins
+ return true;
+ }
+ if (header.IsAction ())
+ {
+ WifiMeshActionHeader actionHdr;
+ packet->RemoveHeader (actionHdr);
+ WifiMeshActionHeader::ActionValue actionValue = actionHdr.GetAction ();
+ // If can not handle - just return;
+ if (actionHdr.GetCategory () != WifiMeshActionHeader::MESH_PEERING_MGT)
+ {
+ return m_protocol->IsActiveLink (m_ifIndex, header.GetAddr2 ());
+ }
+ m_stats.rxMgt++;
+ m_stats.rxMgtBytes += packet->GetSize ();
+ Mac48Address peerAddress = header.GetAddr2 ();
+ Mac48Address peerMpAddress = header.GetAddr3 ();
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ {
+ PeerLinkFrameStart peerFrame;
+ peerFrame.SetPlinkFrameSubtype ((uint8_t) actionValue.peerLink);
+ packet->RemoveHeader (peerFrame);
+ fields = peerFrame.GetFields ();
+ NS_ASSERT (fields.subtype == actionValue.peerLink);
+ }
+ if ((actionValue.peerLink != WifiMeshActionHeader::PEER_LINK_CLOSE) && !(m_parent->CheckSupportedRates (
+ fields.rates)))
+ {
+ m_protocol->ConfigurationMismatch (m_ifIndex, peerAddress);
+ // Broken peer link frame - drop it
+ m_stats.brokenMgt++;
+ return false;
+ }
+ if ((actionValue.peerLink != WifiMeshActionHeader::PEER_LINK_CONFIRM) && !fields.meshId.IsEqual (
+ *(m_protocol->GetMeshId ())))
+ {
+ m_protocol->ConfigurationMismatch (m_ifIndex, peerAddress);
+ // Broken peer link frame - drop it
+ m_stats.brokenMgt++;
+ return false;
+ }
+ Ptr<IePeerManagement> peerElement;
+ //Peer Management element is the last element in this frame - so, we can use WifiInformationElementVector
+ WifiInformationElementVector elements;
+ packet->RemoveHeader (elements);
+ peerElement = DynamicCast<IePeerManagement>(elements.FindFirst(IE11S_PEERING_MANAGEMENT));
+ NS_ASSERT (peerElement != 0);
+ //Check taht frame subtype corresponds peer link subtype
+ if (peerElement->SubtypeIsOpen ())
+ {
+ m_stats.rxOpen++;
+ NS_ASSERT (actionValue.peerLink == WifiMeshActionHeader::PEER_LINK_OPEN);
+ }
+ if (peerElement->SubtypeIsConfirm ())
+ {
+ m_stats.rxConfirm++;
+ NS_ASSERT (actionValue.peerLink == WifiMeshActionHeader::PEER_LINK_CONFIRM);
+ }
+ if (peerElement->SubtypeIsClose ())
+ {
+ m_stats.rxClose++;
+ NS_ASSERT (actionValue.peerLink == WifiMeshActionHeader::PEER_LINK_CLOSE);
+ }
+ //Deliver Peer link management frame to protocol:
+ m_protocol->ReceivePeerLinkFrame (m_ifIndex, peerAddress, peerMpAddress, fields.aid, *peerElement,
+ fields.config);
+ // if we can handle a frame - drop it
+ return false;
+ }
+ return m_protocol->IsActiveLink (m_ifIndex, header.GetAddr2 ());
+}
+bool
+PeerManagementProtocolMac::UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header,
+ Mac48Address from, Mac48Address to)
+{
+ if (header.IsAction ())
+ {
+ WifiMeshActionHeader actionHdr;
+ packet->PeekHeader (actionHdr);
+ WifiMeshActionHeader::ActionValue actionValue = actionHdr.GetAction ();
+ if (actionHdr.GetCategory () == WifiMeshActionHeader::MESH_PEERING_MGT)
+ {
+ return true;
+ }
+ }
+ if (header.GetAddr1 ().IsGroup ())
+ {
+ return true;
+ }
+ else
+ {
+ if (m_protocol->IsActiveLink (m_ifIndex, header.GetAddr1 ()))
+ {
+ return true;
+ }
+ else
+ {
+ m_stats.dropped++;
+ return false;
+ }
+ }
+}
+void
+PeerManagementProtocolMac::UpdateBeacon (MeshWifiBeacon & beacon) const
+{
+ Ptr<IeBeaconTiming> beaconTiming = m_protocol->GetBeaconTimingElement (m_ifIndex);
+ beacon.AddInformationElement (beaconTiming);
+ beacon.AddInformationElement (m_protocol->GetMeshId ());
+}
+
+void
+PeerManagementProtocolMac::SendPeerLinkManagementFrame (Mac48Address peerAddress, Mac48Address peerMpAddress,
+ uint16_t aid, IePeerManagement peerElement, IeConfiguration meshConfig)
+{
+ //Create a packet:
+ meshConfig.SetNeighborCount (m_protocol->GetNumberOfLinks ());
+ Ptr<Packet> packet = Create<Packet> ();
+ WifiInformationElementVector elements;
+ elements.AddInformationElement(Ptr<IePeerManagement> (&peerElement));
+ packet->AddHeader (elements);
+ PeerLinkFrameStart::PlinkFrameStartFields fields;
+ fields.rates = m_parent->GetSupportedRates ();
+ fields.capability = 0;
+ fields.meshId = *(m_protocol->GetMeshId ());
+ fields.config = meshConfig;
+ PeerLinkFrameStart plinkFrame;
+ //Create an 802.11 frame header:
+ //Send management frame to MAC:
+ WifiMeshActionHeader actionHdr;
+ if (peerElement.SubtypeIsOpen ())
+ {
+ m_stats.txOpen++;
+ WifiMeshActionHeader::ActionValue action;
+ action.peerLink = WifiMeshActionHeader::PEER_LINK_OPEN;
+ fields.subtype = WifiMeshActionHeader::PEER_LINK_OPEN;
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PEERING_MGT, action);
+ }
+ if (peerElement.SubtypeIsConfirm ())
+ {
+ m_stats.txConfirm++;
+ WifiMeshActionHeader::ActionValue action;
+ action.peerLink = WifiMeshActionHeader::PEER_LINK_CONFIRM;
+ fields.aid = aid;
+ fields.subtype = WifiMeshActionHeader::PEER_LINK_CONFIRM;
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PEERING_MGT, action);
+ }
+ if (peerElement.SubtypeIsClose ())
+ {
+ m_stats.txClose++;
+ WifiMeshActionHeader::ActionValue action;
+ action.peerLink = WifiMeshActionHeader::PEER_LINK_CLOSE;
+ fields.subtype = WifiMeshActionHeader::PEER_LINK_CLOSE;
+ fields.reasonCode = peerElement.GetReasonCode ();
+ actionHdr.SetAction (WifiMeshActionHeader::MESH_PEERING_MGT, action);
+ }
+ plinkFrame.SetPlinkFrameStart (fields);
+ packet->AddHeader (plinkFrame);
+ packet->AddHeader (actionHdr);
+ m_stats.txMgt++;
+ m_stats.txMgtBytes += packet->GetSize ();
+ // Wifi Mac header:
+ WifiMacHeader hdr;
+ hdr.SetAction ();
+ hdr.SetAddr1 (peerAddress);
+ hdr.SetAddr2 (m_parent->GetAddress ());
+ //Addr is not used here, we use it as our MP address
+ hdr.SetAddr3 (m_protocol->GetAddress ());
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+ m_parent->SendManagementFrame (packet, hdr);
+}
+
+Mac48Address
+PeerManagementProtocolMac::GetAddress () const
+{
+ if (m_parent != 0)
+ {
+ return m_parent->GetAddress ();
+ }
+ else
+ {
+ return Mac48Address::Mac48Address ();
+ }
+}
+std::pair<Time, Time>
+PeerManagementProtocolMac::GetBeaconInfo () const
+{
+ std::pair<Time, Time> retval;
+ retval.first = m_parent->GetTbtt ();
+ retval.second = m_parent->GetBeaconInterval ();
+ return retval;
+}
+void
+PeerManagementProtocolMac::SetBeaconShift (Time shift)
+{
+ if (shift != Seconds (0))
+ {
+ m_stats.beaconShift++;
+ }
+ m_parent->ShiftTbtt (shift);
+}
+PeerManagementProtocolMac::Statistics::Statistics () :
+ txOpen (0), txConfirm (0), txClose (0), rxOpen (0), rxConfirm (0), rxClose (0), dropped (0), brokenMgt (0),
+ txMgt (0), txMgtBytes (0), rxMgt (0), rxMgtBytes (0), beaconShift (0)
+{
+}
+void
+PeerManagementProtocolMac::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "txOpen=\"" << txOpen << "\"" << std::endl <<
+ "txConfirm=\"" << txConfirm << "\"" << std::endl <<
+ "txClose=\"" << txClose << "\"" << std::endl <<
+ "rxOpen=\"" << rxOpen << "\"" << std::endl <<
+ "rxConfirm=\"" << rxConfirm << "\"" << std::endl <<
+ "rxClose=\"" << rxClose << "\"" << std::endl <<
+ "dropped=\"" << dropped << "\"" << std::endl <<
+ "brokenMgt=\"" << brokenMgt << "\"" << std::endl <<
+ "txMgt=\"" << txMgt << "\"" << std::endl <<
+ "txMgtBytes=\"" << txMgtBytes << "\"" << std::endl <<
+ "rxMgt=\"" << rxMgt << "\"" << std::endl <<
+ "rxMgtBytes=\"" << rxMgtBytes << "\"" << std::endl <<
+ "beaconShift=\"" << beaconShift << "\"/>" << std::endl;
+}
+void
+PeerManagementProtocolMac::Report (std::ostream & os) const
+{
+ os << "<PeerManagementProtocolMac "
+ "address=\"" << m_parent->GetAddress () << "\">" << std::endl;
+ m_stats.Print (os);
+ os << "</PeerManagementProtocolMac>" << std::endl;
+}
+void
+PeerManagementProtocolMac::ResetStats ()
+{
+ m_stats = Statistics::Statistics ();
+}
+uint32_t
+PeerManagementProtocolMac::GetLinkMetric (Mac48Address peerAddress)
+{
+ return m_parent->GetLinkMetric (peerAddress);
+}
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-protocol-mac.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,134 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef PEER_MANAGER_MAC_PLUGIN_H_
+#define PEER_MANAGER_MAC_PLUGIN_H_
+
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+
+namespace ns3 {
+class MeshWifiInterfaceMac;
+namespace dot11s {
+class PeerManagementProtocol;
+class IeConfiguration;
+class IePeerManagement;
+class PeerManagementProtocol;
+/**
+ * \ingroup dot11s
+ *
+ * \brief This is plugin to Mesh WiFi MAC, which implements
+ * interface to dot11s peer management protocol: it takes proper
+ * frames from MAC-layer, extracts peer link management information
+ * element and mesh configuration element and passes it to main part
+ * of protocol
+ */
+class PeerManagementProtocolMac : public MeshWifiInterfaceMacPlugin
+{
+public:
+ PeerManagementProtocolMac (uint32_t interface, Ptr<PeerManagementProtocol> protocol);
+ ~PeerManagementProtocolMac ();
+ ///\name Inherited from plugin abstract class
+ ///\{
+ void SetParent (Ptr<MeshWifiInterfaceMac> parent);
+ bool Receive (Ptr<Packet> packet, const WifiMacHeader & header);
+ bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to);
+ void UpdateBeacon (MeshWifiBeacon & beacon) const;
+ ///\}
+ ///\name Statistics:
+ ///\{
+ void Report (std::ostream &) const;
+ void ResetStats ();
+ uint32_t GetLinkMetric (Mac48Address peerAddress);
+ ///\}
+private:
+ friend class PeerManagementProtocol;
+ friend class PeerLink;
+ ///\name BCA functionallity:
+ ///\{
+ ///\brief Fills TBTT and beacon interval. Needed by BCA
+ ///functionallity
+ ///\param first in retval is TBTT
+ ///\param second in retval is beacon interval
+ std::pair<Time, Time> GetBeaconInfo () const;
+ void SetBeaconShift (Time shift);
+ ///\}
+ void SetPeerManagerProtcol (Ptr<PeerManagementProtocol> protocol);
+ void SendPeerLinkManagementFrame (
+ Mac48Address peerAddress,
+ Mac48Address peerMpAddress,
+ uint16_t aid,
+ IePeerManagement peerElement,
+ IeConfiguration meshConfig
+ );
+ ///\brief DUBUG only - to print established links
+ Mac48Address GetAddress () const;
+private:
+ ///\name Information about MAC and protocol:
+ ///\{
+ Ptr<MeshWifiInterfaceMac> m_parent;
+ uint32_t m_ifIndex;
+ Ptr<PeerManagementProtocol> m_protocol;
+ ///\}
+ ///\name Create peer link management frames:
+ ///\{
+ Ptr<Packet> CreatePeerLinkOpenFrame ();
+ Ptr<Packet> CreatePeerLinkConfirmFrame ();
+ Ptr<Packet> CreatePeerLinkCloseFrame ();
+ ///This structure keeps all fields in peer link management frame,
+ ///which are not subclasses of WifiInformationElement
+ struct PlinkFrameStart {
+ uint8_t subtype;
+ uint16_t aid;
+ SupportedRates rates;
+ uint16_t qos;
+ };
+ /// \name Parses the start of the frame, where there are no
+ /// WifiInformationElements exist
+ PlinkFrameStart ParsePlinkFrame (Ptr<const Packet> packet);
+ ///\}
+ ///// Closes link when a proper number of successive transmissions have failed
+ void TxError (WifiMacHeader const &hdr);
+ void TxOk (WifiMacHeader const &hdr);
+ //Keeps statistics
+ struct Statistics {
+ uint16_t txOpen;
+ uint16_t txConfirm;
+ uint16_t txClose;
+ uint16_t rxOpen;
+ uint16_t rxConfirm;
+ uint16_t rxClose;
+ uint16_t dropped;
+ uint16_t brokenMgt;
+ uint16_t txMgt;
+ uint32_t txMgtBytes;
+ uint16_t rxMgt;
+ uint32_t rxMgtBytes;
+ uint16_t beaconShift;
+
+ Statistics ();
+ void Print (std::ostream & os) const;
+ };
+ struct Statistics m_stats;
+};
+
+} // namespace dot11s
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-protocol.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,578 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+#include "peer-management-protocol.h"
+
+#include "ie-dot11s-peer-management.h"
+#include "ie-dot11s-configuration.h"
+
+#include "ns3/mesh-point-device.h"
+#include "ns3/simulator.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/random-variable.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+#include "ns3/wifi-net-device.h"
+#include "peer-link.h"
+
+NS_LOG_COMPONENT_DEFINE ("PeerManagementProtocol");
+namespace ns3 {
+namespace dot11s {
+/***************************************************
+ * PeerManager
+ ***************************************************/
+NS_OBJECT_ENSURE_REGISTERED (PeerManagementProtocol);
+
+TypeId
+PeerManagementProtocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::dot11s::PeerManagementProtocol")
+ .SetParent<Object> ()
+ .AddConstructor<PeerManagementProtocol> ()
+ // maximum number of peer links. Now we calculate the total
+ // number of peer links on all interfaces
+ .AddAttribute ( "MaxNumberOfPeerLinks",
+ "Maximum number of peer links",
+ UintegerValue (32),
+ MakeUintegerAccessor (
+ &PeerManagementProtocol::m_maxNumberOfPeerLinks),
+ MakeUintegerChecker<uint8_t> ()
+ )
+ .AddAttribute ( "MaxBeaconLossForBeaconTiming",
+ "If maximum number of beacons were lost, station will not included in beacon timing element",
+ UintegerValue (3),
+ MakeUintegerAccessor (
+ &PeerManagementProtocol::m_maxBeaconLostForBeaconTiming),
+ MakeUintegerChecker<uint8_t> ()
+ )
+ ;
+ return tid;
+}
+PeerManagementProtocol::PeerManagementProtocol () :
+ m_lastAssocId (0), m_lastLocalLinkId (1), m_maxBeaconLostForBeaconTiming (3)
+{
+}
+PeerManagementProtocol::~PeerManagementProtocol ()
+{
+}
+void
+PeerManagementProtocol::DoDispose ()
+{
+ //cancel cleanup event and go through the map of peer links,
+ //deleting each
+ for (PeerLinksMap::iterator j = m_peerLinks.begin (); j != m_peerLinks.end (); j++)
+ {
+ for (PeerLinksOnInterface::iterator i = j->second.begin (); i != j->second.end (); i++)
+ {
+ (*i) = 0;
+ }
+ j->second.clear ();
+ }
+ m_peerLinks.clear ();
+ //cleaning beacon structures:
+ for (BeaconInfoMap::iterator i = m_neighbourBeacons.begin (); i != m_neighbourBeacons.end (); i++)
+ {
+ i->second.clear ();
+ }
+ m_neighbourBeacons.clear ();
+}
+
+bool
+PeerManagementProtocol::Install (Ptr<MeshPointDevice> mp)
+{
+ std::vector<Ptr<NetDevice> > interfaces = mp->GetInterfaces ();
+ for (std::vector<Ptr<NetDevice> >::iterator i = interfaces.begin (); i != interfaces.end (); i++)
+ {
+ Ptr<WifiNetDevice> wifiNetDev = (*i)->GetObject<WifiNetDevice> ();
+ if (wifiNetDev == 0)
+ {
+ return false;
+ }
+ Ptr<MeshWifiInterfaceMac> mac = wifiNetDev->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ if (mac == 0)
+ {
+ return false;
+ }
+ Ptr<PeerManagementProtocolMac> plugin = Create<PeerManagementProtocolMac> ((*i)->GetIfIndex (), this);
+ mac->InstallPlugin (plugin);
+ m_plugins[(*i)->GetIfIndex ()] = plugin;
+ PeerLinksOnInterface newmap;
+ m_peerLinks[(*i)->GetIfIndex ()] = newmap;
+ }
+ // Mesh point aggregates all installed protocols
+ m_address = Mac48Address::ConvertFrom (mp->GetAddress ());
+ mp->AggregateObject (this);
+ return true;
+}
+
+Ptr<IeBeaconTiming>
+PeerManagementProtocol::GetBeaconTimingElement (uint32_t interface)
+{
+ Ptr<IeBeaconTiming> retval = Create<IeBeaconTiming> ();
+ BeaconInfoMap::iterator i = m_neighbourBeacons.find (interface);
+ if (i == m_neighbourBeacons.end ())
+ {
+ return retval;
+ }
+ bool cleaned = false;
+ while (!cleaned)
+ {
+ BeaconsOnInterface::iterator start = i->second.begin ();
+ for (BeaconsOnInterface::iterator j = start; j != i->second.end (); j++)
+ {
+ //check beacon loss and make a timing element
+ //if last beacon was m_maxBeaconLostForBeaconTiming beacons ago - we do not put it to the
+ //timing element
+ if ((j->second.referenceTbtt + j->second.beaconInterval * Scalar (m_maxBeaconLostForBeaconTiming))
+ < Simulator::Now ())
+ {
+ start = j;
+ i->second.erase (j);
+ break;
+ }
+ }
+ cleaned = true;
+ }
+ for (BeaconsOnInterface::const_iterator j = i->second.begin (); j != i->second.end (); j++)
+ {
+ retval->AddNeighboursTimingElementUnit (j->second.aid, j->second.referenceTbtt,
+ j->second.beaconInterval);
+ }
+ return retval;
+}
+
+void
+PeerManagementProtocol::FillBeaconInfo (uint32_t interface, Mac48Address peerAddress, Time receivingTime,
+ Time beaconInterval)
+{
+ BeaconInfoMap::iterator i = m_neighbourBeacons.find (interface);
+ if (i == m_neighbourBeacons.end ())
+ {
+ BeaconsOnInterface newMap;
+ m_neighbourBeacons[interface] = newMap;
+ }
+ i = m_neighbourBeacons.find (interface);
+ BeaconsOnInterface::iterator j = i->second.find (peerAddress);
+ if (j == i->second.end ())
+ {
+ BeaconInfo newInfo;
+ newInfo.referenceTbtt = receivingTime;
+ newInfo.beaconInterval = beaconInterval;
+ newInfo.aid = m_lastAssocId++;
+ if (m_lastAssocId == 0xff)
+ {
+ m_lastAssocId = 0;
+ }
+ i->second[peerAddress] = newInfo;
+ }
+ else
+ {
+ j->second.referenceTbtt = receivingTime;
+ j->second.beaconInterval = beaconInterval;
+ }
+}
+
+void
+PeerManagementProtocol::UpdatePeerBeaconTiming (uint32_t interface, bool meshBeacon,
+ IeBeaconTiming timingElement, Mac48Address peerAddress, Time receivingTime, Time beaconInterval)
+{
+ FillBeaconInfo (interface, peerAddress, receivingTime, beaconInterval);
+ if (!meshBeacon)
+ {
+ return;
+ }
+ //BCA:
+ PeerManagementProtocolMacMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT (plugin != m_plugins.end ());
+ Time shift = GetNextBeaconShift (interface);
+ if (TimeToTu (shift) != 0)
+ {
+ plugin->second->SetBeaconShift (shift);
+ }
+ //PM STATE Machine
+ //Check that a given beacon is not from our interface
+ for (PeerManagementProtocolMacMap::const_iterator i = m_plugins.begin (); i != m_plugins.end (); i++)
+ {
+ if (i->second->GetAddress () == peerAddress)
+ {
+ return;
+ }
+ }
+ Ptr<PeerLink> peerLink = FindPeerLink (interface, peerAddress);
+ if (peerLink != 0)
+ {
+ peerLink->SetBeaconTimingElement (timingElement);
+ peerLink->SetBeaconInformation (receivingTime, beaconInterval);
+ }
+ else
+ {
+ if (ShouldSendOpen (interface, peerAddress))
+ {
+ peerLink = InitiateLink (interface, peerAddress, Mac48Address::GetBroadcast (), receivingTime,
+ beaconInterval);
+ peerLink->SetBeaconTimingElement (timingElement);
+ peerLink->MLMEActivePeerLinkOpen ();
+ }
+ }
+}
+
+void
+PeerManagementProtocol::ReceivePeerLinkFrame (uint32_t interface, Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress, uint16_t aid, IePeerManagement peerManagementElement,
+ IeConfiguration meshConfig)
+{
+ Ptr<PeerLink> peerLink = FindPeerLink (interface, peerAddress);
+ if (peerManagementElement.SubtypeIsOpen ())
+ {
+ PmpReasonCode reasonCode;
+ bool reject = !(ShouldAcceptOpen (interface, peerAddress, reasonCode));
+ if (peerLink == 0)
+ {
+ peerLink = InitiateLink (interface, peerAddress, peerMeshPointAddress, Simulator::Now (), Seconds (
+ 1.0));
+ }
+ if (!reject)
+ {
+ peerLink->OpenAccept (peerManagementElement.GetLocalLinkId (), meshConfig, peerMeshPointAddress);
+ }
+ else
+ {
+ peerLink->OpenReject (peerManagementElement.GetLocalLinkId (), meshConfig, peerMeshPointAddress,
+ reasonCode);
+ }
+ }
+ if (peerLink == 0)
+ {
+ return;
+ }
+ if (peerManagementElement.SubtypeIsConfirm ())
+ {
+ peerLink->ConfirmAccept (peerManagementElement.GetLocalLinkId (),
+ peerManagementElement.GetPeerLinkId (), aid, meshConfig, peerMeshPointAddress);
+ }
+ if (peerManagementElement.SubtypeIsClose ())
+ {
+ peerLink->Close (peerManagementElement.GetLocalLinkId (), peerManagementElement.GetPeerLinkId (),
+ peerManagementElement.GetReasonCode ());
+ }
+}
+void
+PeerManagementProtocol::ConfigurationMismatch (uint32_t interface, Mac48Address peerAddress)
+{
+ Ptr<PeerLink> peerLink = FindPeerLink (interface, peerAddress);
+ if (peerLink != 0)
+ {
+ peerLink->MLMECancelPeerLink (REASON11S_MESH_CAPABILITY_POLICY_VIOLATION);
+ }
+}
+void
+PeerManagementProtocol::TransmissionFailure (uint32_t interface, Mac48Address peerAddress)
+{
+ NS_LOG_DEBUG("transmission failed between "<<GetAddress () << " and " << peerAddress << " failed, link will be colsed");
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if (peerLink != 0)
+ {
+ peerLink->TransmissionFailure ();
+ }
+}
+void
+PeerManagementProtocol::TransmissionSuccess (uint32_t interface, Mac48Address peerAddress)
+{
+ NS_LOG_DEBUG("transmission success "<<GetAddress () << " and " << peerAddress << " failed, link will be colsed");
+ Ptr<PeerLink> peerLink = FindPeerLink(interface, peerAddress);
+ if (peerLink != 0)
+ {
+ peerLink->TransmissionSuccess ();
+ }
+}
+Ptr<PeerLink>
+PeerManagementProtocol::InitiateLink (uint32_t interface, Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress, Time lastBeacon, Time beaconInterval)
+{
+ Ptr<PeerLink> new_link = CreateObject<PeerLink> ();
+ if (m_lastLocalLinkId == 0xff)
+ {
+ m_lastLocalLinkId = 0;
+ }
+ //find a beacon entry
+ BeaconInfoMap::iterator beaconsOnInterface = m_neighbourBeacons.find (interface);
+ if (beaconsOnInterface == m_neighbourBeacons.end ())
+ {
+ FillBeaconInfo (interface, peerAddress, lastBeacon, beaconInterval);
+ }
+ beaconsOnInterface = m_neighbourBeacons.find (interface);
+ BeaconsOnInterface::iterator beacon = beaconsOnInterface->second.find (peerAddress);
+ if (beacon == beaconsOnInterface->second.end ())
+ {
+ FillBeaconInfo (interface, peerAddress, lastBeacon, beaconInterval);
+ }
+ beacon = beaconsOnInterface->second.find (peerAddress);
+ //find a peer link - it must not exist
+ if (FindPeerLink (interface, peerAddress) != 0)
+ {
+ NS_FATAL_ERROR ("Peer link must not exist.");
+ }
+ // Plugin must exist
+ PeerManagementProtocolMacMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT (plugin != m_plugins.end ());
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end ());
+ new_link->SetLocalAid (beacon->second.aid);
+ new_link->SetInterface (interface);
+ new_link->SetLocalLinkId (m_lastLocalLinkId++);
+ new_link->SetPeerAddress (peerAddress);
+ new_link->SetPeerMeshPointAddress (peerMeshPointAddress);
+ new_link->SetBeaconInformation (lastBeacon, beaconInterval);
+ new_link->SetMacPlugin (plugin->second);
+ new_link->MLMESetSignalStatusCallback (MakeCallback (&PeerManagementProtocol::PeerLinkStatus, this));
+ iface->second.push_back (new_link);
+ return new_link;
+}
+Ptr<PeerLink>
+PeerManagementProtocol::FindPeerLink (uint32_t interface, Mac48Address peerAddress)
+{
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end ());
+ for (PeerLinksOnInterface::iterator i = iface->second.begin (); i != iface->second.end (); i++)
+ {
+ if ((*i)->GetPeerAddress () == peerAddress)
+ {
+ if ((*i)->LinkIsIdle ())
+ {
+ (*i) = 0;
+ (iface->second).erase (i);
+ return 0;
+ }
+ else
+ {
+ return (*i);
+ }
+ }
+ }
+ return 0;
+}
+void
+PeerManagementProtocol::SetPeerLinkStatusCallback (
+ Callback<void, Mac48Address, Mac48Address, uint32_t, bool> cb)
+{
+ m_peerStatusCallback = cb;
+}
+std::vector<Mac48Address>
+PeerManagementProtocol::GetActiveLinks (uint32_t interface)
+{
+ std::vector<Mac48Address> retval;
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end ());
+ for (PeerLinksOnInterface::iterator i = iface->second.begin (); i != iface->second.end (); i++)
+ {
+ if ((*i)->LinkIsEstab ())
+ {
+ retval.push_back ((*i)->GetPeerAddress ());
+ }
+ }
+ return retval;
+}
+bool
+PeerManagementProtocol::IsActiveLink (uint32_t interface, Mac48Address peerAddress)
+{
+ Ptr<PeerLink> peerLink = FindPeerLink (interface, peerAddress);
+ if (peerLink != 0)
+ {
+ return (peerLink->LinkIsEstab ());
+ }
+ return false;
+}
+bool
+PeerManagementProtocol::ShouldSendOpen (uint32_t interface, Mac48Address peerAddress)
+{
+ return (m_stats.linksTotal <= m_maxNumberOfPeerLinks);
+}
+bool
+PeerManagementProtocol::ShouldAcceptOpen (uint32_t interface, Mac48Address peerAddress,
+ PmpReasonCode & reasonCode)
+{
+ if (m_stats.linksTotal > m_maxNumberOfPeerLinks)
+ {
+ reasonCode = REASON11S_MESH_MAX_PEERS;
+ return false;
+ }
+ return true;
+}
+Time
+PeerManagementProtocol::GetNextBeaconShift (uint32_t interface)
+{
+ //REMINDER:: in timing element 1) last beacon reception time is measured in units of 256 microseconds
+ // 2) beacon interval is mesured in units of 1024 microseconds
+ // 3) hereafter TU = 1024 microseconds
+ //So, the shift is a random integer variable uniformly distributed in [-15;-1] U [1;15]
+ static int maxShift = 15;
+ static int minShift = 1;
+ PeerLinksMap::iterator iface = m_peerLinks.find (interface);
+ NS_ASSERT (iface != m_peerLinks.end ());
+ PeerManagementProtocolMacMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT (plugin != m_plugins.end ());
+ std::pair<Time, Time> myBeacon = plugin->second->GetBeaconInfo ();
+ if (Simulator::Now () + TuToTime (maxShift) > myBeacon.first + myBeacon.second)
+ {
+ return MicroSeconds (0);
+ }
+ for (PeerLinksOnInterface::iterator i = iface->second.begin (); i != iface->second.end (); i++)
+ {
+ IeBeaconTiming::NeighboursTimingUnitsList neighbours;
+ if ((*i)->LinkIsIdle ())
+ {
+ continue;
+ }
+ neighbours = (*i)->GetBeaconTimingElement ().GetNeighboursTimingElementsList ();
+ //Going through all my timing elements and detecting future beacon collisions
+ for (IeBeaconTiming::NeighboursTimingUnitsList::const_iterator j = neighbours.begin (); j
+ != neighbours.end (); j++)
+ {
+ //We apply MBAC only if beacon Intervals are equal
+ if ((*j)->GetBeaconInterval () == TimeToTu (myBeacon.second))
+ {
+ //Apply MBCA if future beacons may coinside
+ if ((TimeToTu (myBeacon.first) - ((*j)->GetLastBeacon () / 4)) % ((*j)->GetBeaconInterval ())
+ == 0)
+ {
+ UniformVariable randomSign (-1, 1);
+ UniformVariable randomShift (minShift, maxShift);
+ int beaconShift = randomShift.GetInteger (minShift, maxShift) * ((randomSign.GetValue ()
+ >= 0) ? 1 : -1);
+ NS_LOG_DEBUG ("Apply MBCA: Shift value = " << beaconShift << " beacon TUs");
+ //Do not shift to the past!
+ return (TuToTime (beaconShift) + Simulator::Now () < myBeacon.first) ? TuToTime (
+ beaconShift) : TuToTime (0);
+ }
+ }
+ }
+ }
+ return MicroSeconds (0);
+}
+Time
+PeerManagementProtocol::TuToTime (uint32_t x)
+{
+ return MicroSeconds (x * 1024);
+}
+uint32_t
+PeerManagementProtocol::TimeToTu (Time x)
+{
+ return (uint32_t) (x.GetMicroSeconds () / 1024);
+}
+void
+PeerManagementProtocol::PeerLinkStatus (uint32_t interface, Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress, PeerLink::PeerState ostate, PeerLink::PeerState nstate)
+{
+ PeerManagementProtocolMacMap::iterator plugin = m_plugins.find (interface);
+ NS_ASSERT (plugin != m_plugins.end ());
+ NS_LOG_DEBUG ("Link between me:" << m_address << " my interface:" << plugin->second->GetAddress ()
+ << " and peer mesh point:" << peerMeshPointAddress << " and its interface:" << peerAddress
+ << ", at my interface ID:" << interface << ". State movement:" << ostate << " -> " << nstate);
+ if ((nstate == PeerLink::ESTAB) && (ostate != PeerLink::ESTAB))
+ {
+ m_stats.linksOpened++;
+ m_stats.linksTotal++;
+ if (!m_peerStatusCallback.IsNull ())
+ {
+ m_peerStatusCallback (peerMeshPointAddress, peerAddress, interface, true);
+ }
+ }
+ if ((ostate == PeerLink::ESTAB) && (nstate != PeerLink::ESTAB))
+ {
+ m_stats.linksClosed++;
+ m_stats.linksTotal--;
+ if (!m_peerStatusCallback.IsNull ())
+ {
+ m_peerStatusCallback (peerMeshPointAddress, peerAddress, interface, false);
+ }
+ }
+ if (nstate == PeerLink::IDLE)
+ {
+ Ptr<PeerLink> link = FindPeerLink (interface, peerAddress);
+ NS_ASSERT (link == 0);
+ }
+}
+uint8_t
+PeerManagementProtocol::GetNumberOfLinks ()
+{
+ return m_stats.linksTotal;
+}
+Ptr<IeMeshId>
+PeerManagementProtocol::GetMeshId () const
+{
+ NS_ASSERT (m_meshId != 0);
+ return m_meshId;
+}
+void
+PeerManagementProtocol::SetMeshId (std::string s)
+{
+ m_meshId = Create<IeMeshId> (s);
+}
+Mac48Address
+PeerManagementProtocol::GetAddress ()
+{
+ return m_address;
+}
+PeerManagementProtocol::Statistics::Statistics (uint16_t t) :
+ linksTotal (t), linksOpened (0), linksClosed (0)
+{
+}
+void
+PeerManagementProtocol::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "linksTotal=\"" << linksTotal << "\" "
+ "linksOpened=\"" << linksOpened << "\" "
+ "linksClosed=\"" << linksClosed << "\"/>" << std::endl;
+}
+void
+PeerManagementProtocol::Report (std::ostream & os) const
+{
+ os << "<PeerManagementProtocol>" << std::endl;
+ m_stats.Print (os);
+ for (PeerManagementProtocolMacMap::const_iterator plugins = m_plugins.begin (); plugins != m_plugins.end (); plugins++)
+ {
+ //Take statistics from plugin:
+ plugins->second->Report (os);
+ //Print all active peer links:
+ PeerLinksMap::const_iterator iface = m_peerLinks.find (plugins->second->m_ifIndex);
+ NS_ASSERT (iface != m_peerLinks.end ());
+ for (PeerLinksOnInterface::const_iterator i = iface->second.begin (); i != iface->second.end (); i++)
+ {
+ (*i)->Report (os);
+ }
+ }
+ os << "</PeerManagementProtocol>" << std::endl;
+}
+void
+PeerManagementProtocol::ResetStats ()
+{
+ m_stats = Statistics::Statistics (m_stats.linksTotal); // don't reset number of links
+ for (PeerManagementProtocolMacMap::const_iterator plugins = m_plugins.begin (); plugins != m_plugins.end (); plugins++)
+ {
+ plugins->second->ResetStats ();
+ }
+}
+
+} // namespace dot11s
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/peer-management-protocol.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+#ifndef DOT11S_PEER_MAN_H
+#define DOT11S_PEER_MAN_H
+
+#include "ns3/mac48-address.h"
+#include "ns3/net-device.h"
+#include "ns3/event-id.h"
+#include "ns3/nstime.h"
+#include "ie-dot11s-beacon-timing.h"
+#include "ie-dot11s-peer-management.h"
+#include "ie-dot11s-id.h"
+#include "peer-link.h"
+
+#include <map>
+namespace ns3 {
+class MeshPointDevice;
+namespace dot11s {
+class PeerManagementProtocolMac;
+class PeerLink;
+class IePeerManagement;
+class IeConfiguration;
+/**
+ * \ingroup dot11s
+ *
+ * \brief 802.11s Peer Management Protocol model
+ */
+class PeerManagementProtocol : public Object
+{
+public:
+ PeerManagementProtocol ();
+ ~PeerManagementProtocol ();
+ static TypeId GetTypeId ();
+ void DoDispose ();
+ /**
+ * \brief Install PMP on given mesh point.
+ *
+ * Installing protocol cause installing its interface MAC plugins.
+ *
+ * Also MP aggregates all installed protocols, PMP protocol can be accessed
+ * via MeshPointDevice::GetObject<PeerManagementProtocol>();
+ */
+ bool Install (Ptr<MeshPointDevice>);
+ /**
+ * \brief Methods that handle beacon sending/receiving procedure.
+ *
+ * This methods interact with MAC_layer plug-in
+ * \{
+ */
+ /**
+ * \brief When we are sending a beacon - we fill beacon timing
+ * element
+ * \param IeBeaconTiming is a beacon timing element that
+ * should be present in beacon
+ * \param interface is a interface sending a beacon
+ */
+ Ptr<IeBeaconTiming> GetBeaconTimingElement (uint32_t interface);
+ /**
+ * \brief When we receive a beacon from peer-station, we remember
+ * its beacon timing element (needed for peer choosing mechanism),
+ * and remember beacon timers - last beacon and beacon interval to
+ * detect beacon loss and cancel links
+ * \param interface is a interface on which beacon was received
+ * \param timingElement is a timing element of remote beacon
+ */
+ void UpdatePeerBeaconTiming (
+ uint32_t interface,
+ bool meshBeacon,
+ IeBeaconTiming timingElement,
+ Mac48Address peerAddress,
+ Time receivingTime,
+ Time beaconInterval
+ );
+ //\}
+ /**
+ * \brief Methods that handle Peer link management frames
+ * interaction:
+ * \{
+ */
+ /**
+ * Deliver Peer link management information to the protocol-part
+ * \param void is returning value - we pass a frame and forget
+ * about it
+ * \param uint32_t - is a interface ID of a given MAC (interfaceID rather
+ * than MAC address, beacause many interfaces may have the same MAC)
+ * \param Mac48Address is address of peer
+ * \param Mac48Address is address of peer mesh point device (equal
+ * to peer address when only one interface)
+ * \param uint16_t is association ID, which peer has assigned to
+ * us
+ * \param IeConfiguration is mesh configuration element
+ * taken from the peer management frame
+ * \param IePeerManagement is peer link management element
+ */
+ void ReceivePeerLinkFrame (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ uint16_t aid,
+ IePeerManagement peerManagementElement,
+ IeConfiguration meshConfig
+ );
+ /**
+ * Cancell peer link due to broken configuration (SSID or Supported
+ * rates)
+ */
+ void ConfigurationMismatch (uint32_t interface, Mac48Address peerAddress);
+ /**
+ * Cancel peer link due to successive transmission failures
+ */
+ void TransmissionFailure (uint32_t interface, const Mac48Address peerAddress);
+ void TransmissionSuccess (uint32_t interface, const Mac48Address peerAddress);
+ /**
+ * Checks if there is established link
+ */
+ bool IsActiveLink (uint32_t interface, Mac48Address peerAddress);
+ //\}
+ ///\brief Needed by external module to do MLME
+ Ptr<PeerLink> FindPeerLink (uint32_t interface, Mac48Address peerAddress);
+ void SetPeerLinkStatusCallback (Callback<void, Mac48Address, Mac48Address, uint32_t, bool> cb);
+ std::vector<Mac48Address> GetActiveLinks (uint32_t interface);
+ ///\brief needed by plugins to set global source address
+ Mac48Address GetAddress ();
+ ///\Needed to fill mesh configuration
+ uint8_t GetNumberOfLinks ();
+ void SetMeshId (std::string s);
+ Ptr<IeMeshId> GetMeshId () const;
+ ///\brief: Report statistics
+ void Report (std::ostream &) const;
+ void ResetStats ();
+private:
+ /** \name Private structures
+ * \{
+ */
+ /// Keeps information about beacon of peer station: beacon interval, association ID, last time we have received a beacon
+ struct BeaconInfo
+ {
+ uint16_t aid; //Assoc ID
+ Time referenceTbtt; //When one of my station's beacons was put into a beacon queue;
+ Time beaconInterval; //Beacon interval of my station;
+ };
+ /// We keep a vector of pointers to PeerLink class. This vector
+ /// keeps all peer links at a given interface.
+ typedef std::vector<Ptr<PeerLink> > PeerLinksOnInterface;
+ /// This map keeps all peer links.
+ ///\param uint32_t is interface ID
+ typedef std::map<uint32_t, PeerLinksOnInterface> PeerLinksMap;
+ ///\brief This map keeps relationship between peer address and its
+ /// beacon information
+ typedef std::map<Mac48Address, BeaconInfo> BeaconsOnInterface;
+ ///\brief This map keeps beacon information on all intefaces
+ typedef std::map<uint32_t, BeaconsOnInterface> BeaconInfoMap;
+ ///\brief this vector keeps pointers to MAC-plugins
+ typedef std::map<uint32_t, Ptr<PeerManagementProtocolMac> > PeerManagementProtocolMacMap;
+ ///\}
+private:
+ /**
+ * Return a position in beacon-storage for a given remote station
+ */
+ void FillBeaconInfo (uint32_t interface, Mac48Address peerAddress, Time receivingTime, Time beaconInterval);
+ Ptr<PeerLink> InitiateLink (
+ uint32_t interface,
+ Mac48Address peerAddress,
+ Mac48Address peerMeshPointAddress,
+ Time lastBeacon,
+ Time beaconInterval
+ );
+ /**
+ * \name External peer-chooser
+ * \{
+ */
+ bool ShouldSendOpen (uint32_t interface, Mac48Address peerAddress);
+ bool ShouldAcceptOpen (uint32_t interface, Mac48Address peerAddress, PmpReasonCode & reasonCode);
+ /**
+ * \}
+ * \brief Indicates changes in peer links
+ */
+ void PeerLinkStatus (uint32_t interface, Mac48Address peerAddress, Mac48Address peerMeshPointAddres, PeerLink::PeerState ostate, PeerLink::PeerState nstate);
+ ///\brief BCA
+ Time GetNextBeaconShift (uint32_t interface);
+ /**
+ * \name Time<-->TU converters:
+ * \{
+ */
+ Time TuToTime (uint32_t x);
+ uint32_t TimeToTu (Time x);
+ ///\}
+private:
+ PeerManagementProtocolMacMap m_plugins;
+ Mac48Address m_address;
+ Ptr<IeMeshId> m_meshId;
+ /**
+ * \name Information related to beacons:
+ * \{
+ */
+ BeaconInfoMap m_neighbourBeacons;
+ ///\}
+ uint16_t m_lastAssocId;
+ uint16_t m_lastLocalLinkId;
+ uint8_t m_maxNumberOfPeerLinks;
+ uint8_t m_maxBeaconLostForBeaconTiming;
+ /**
+ * Peer Links
+ * \{
+ */
+ PeerLinksMap m_peerLinks;
+ /**
+ * \}
+ */
+ ///\brief Callback to notify about peer link changes:
+ ///\param Mac48Address is peer address of mesh point
+ ///\param Mac48Address is peer address of interface
+ ///\param uint32_t - interface ID
+ ///\param bool is staus - true when new link has appeared, false -
+ //when link was closed
+ Callback <void, Mac48Address, Mac48Address, uint32_t, bool> m_peerStatusCallback;
+ ///\}
+ //Keeps statistics
+ struct Statistics {
+ uint16_t linksTotal;
+ uint16_t linksOpened;
+ uint16_t linksClosed;
+
+ Statistics (uint16_t t = 0);
+ void Print (std::ostream & os) const;
+ };
+ struct Statistics m_stats;
+
+};
+
+} // namespace dot11s
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/waf Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../../waf "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/dot11s/wscript Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,32 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_module('dot11s', ['wifi'])
+ obj.source = [
+ 'ie-dot11s-beacon-timing.cc',
+ 'ie-dot11s-configuration.cc',
+ 'ie-dot11s-id.cc',
+ 'ie-dot11s-peer-management.cc',
+ 'ie-dot11s-preq.cc',
+ 'ie-dot11s-prep.cc',
+ 'ie-dot11s-perr.cc',
+ 'ie-dot11s-rann.cc',
+ 'ie-dot11s-peering-protocol.cc',
+ 'ie-dot11s-metric-report.cc',
+ 'dot11s-mac-header.cc',
+ 'peer-link-frame.cc',
+ 'peer-link.cc',
+ 'peer-management-protocol-mac.cc',
+ 'peer-management-protocol.cc',
+ 'hwmp-tag.cc',
+ 'hwmp-rtable.cc',
+ 'hwmp-protocol-mac.cc',
+ 'hwmp-protocol.cc',
+ 'airtime-metric.cc',
+ 'dot11s-installer.cc',
+ ]
+ headers = bld.new_task_gen('ns3header')
+ headers.module = 'dot11s'
+ headers.source = [
+ 'dot11s-installer.h',
+ ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-header.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#include "ns3/packet.h"
+#include "ns3/test.h"
+
+#include "flame-header.h"
+
+namespace ns3 {
+namespace flame {
+FlameHeader::FlameHeader () :
+ m_cost (0), m_seqno (0), m_origDst (Mac48Address ()), m_origSrc (Mac48Address ())
+{
+}
+FlameHeader::~FlameHeader ()
+{
+}
+TypeId
+FlameHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::FlameHeader")
+ .SetParent<Header> ()
+ .AddConstructor<FlameHeader> ();
+ return tid;
+}
+TypeId
+FlameHeader::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+void
+FlameHeader::Print (std::ostream &os) const
+{
+ os << "Cost = " << (uint16_t) m_cost << std::endl << "Sequence number = " << m_seqno
+ << std::endl << "Orig Destination = " << m_origDst << std::endl << "Orig Source = " << m_origSrc << std::endl;
+}
+uint32_t
+FlameHeader::GetSerializedSize (void) const
+{
+ return 1 // Reserved
+ + 1 // Cost
+ + 2 // Seqno
+ + 6 // Orig Dst
+ + 6 // Orig Src
+ + 2 // Flame Port
+ ;
+}
+void
+FlameHeader::Serialize (Buffer::Iterator start) const
+{
+ Buffer::Iterator i = start;
+ i.WriteU8 (0); //Reserved
+ i.WriteU8 (m_cost); //Cost
+ i.WriteHtonU16 (m_seqno); //Seqno
+ WriteTo (i, m_origDst);
+ WriteTo (i, m_origSrc);
+ i.WriteHtonU16 (m_protocol);
+}
+uint32_t
+FlameHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ i.Next (1);
+ m_cost = i.ReadU8 ();
+ m_seqno = i.ReadNtohU16 ();
+ ReadFrom (i, m_origDst);
+ ReadFrom (i, m_origSrc);
+ m_protocol = i.ReadNtohU16 ();
+ return i.GetDistanceFrom (start);
+}
+void
+FlameHeader::AddCost (uint8_t cost)
+{
+ m_cost = (((uint16_t) cost + (uint16_t) m_cost) > 255) ? 255 : cost + m_cost;
+}
+uint8_t
+FlameHeader::GetCost () const
+{
+ return m_cost;
+}
+void
+FlameHeader::SetSeqno (uint16_t seqno)
+{
+ m_seqno = seqno;
+}
+uint16_t
+FlameHeader::GetSeqno () const
+{
+ return m_seqno;
+}
+void
+FlameHeader::SetOrigDst (Mac48Address dst)
+{
+ m_origDst = dst;
+}
+Mac48Address
+FlameHeader::GetOrigDst () const
+{
+ return m_origDst;
+}
+void
+FlameHeader::SetOrigSrc (Mac48Address src)
+{
+ m_origSrc = src;
+}
+Mac48Address
+FlameHeader::GetOrigSrc () const
+{
+ return m_origSrc;
+}
+void
+FlameHeader::SetProtocol (uint16_t protocol)
+{
+ m_protocol = protocol;
+}
+uint16_t
+FlameHeader::GetProtocol () const
+{
+ return m_protocol;
+}
+bool
+operator== (const FlameHeader & a, const FlameHeader & b)
+{
+ return ((a.m_cost == b.m_cost) && (a.m_seqno == b.m_seqno) && (a.m_origDst == b.m_origDst) && (a.m_origSrc
+ == b.m_origSrc) && (a.m_protocol == b.m_protocol));
+}
+
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for FlameHeader
+struct FlameHeaderBist : public Test
+{
+ FlameHeaderBist () :
+ Test ("Mesh/Flame/FlameHeader")
+ {
+ }
+ virtual bool
+ RunTests ();
+};
+
+/// Test instance
+static FlameHeaderBist g_FlameHeaderBist;
+
+bool
+FlameHeaderBist::RunTests ()
+{
+ bool result (true);
+ FlameHeader a;
+ a.AddCost (123);
+ a.SetSeqno (456);
+ a.SetOrigDst (Mac48Address ("11:22:33:44:55:66"));
+ a.SetOrigSrc (Mac48Address ("00:11:22:33:44:55"));
+ a.SetProtocol (0x806);
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (a);
+ FlameHeader b;
+ packet->RemoveHeader (b);
+ NS_TEST_ASSERT_EQUAL (b, a);
+ return result;
+}
+#endif
+
+} //namespace flame
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-header.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef FLAME_HEADER_H
+#define FLAME_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/mac48-address.h"
+
+namespace ns3 {
+namespace flame {
+/**
+ * \ingroup flame
+ *
+ * \brief Flame header
+ *
+ * Header format: | Reserved: 1 | cost: 1 | Sequence number: 2 | OrigDst: 6 | OrigSrc: 6 | Flame port : 2 |
+ */
+
+class FlameHeader : public Header
+{
+public:
+
+ FlameHeader ();
+ ~FlameHeader ();
+ /**
+ * \name Inherited from Header class:
+ * \{
+ */
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+ virtual void Print (std::ostream &os) const;
+ virtual uint32_t GetSerializedSize (void) const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+ ///\}
+ /**
+ * \name Seeters/Getters for fields:
+ * \{
+ */
+ void AddCost (uint8_t cost);
+ uint8_t GetCost () const;
+ void SetSeqno (uint16_t seqno);
+ uint16_t GetSeqno () const;
+ void SetOrigDst (Mac48Address dst);
+ Mac48Address GetOrigDst () const;
+ void SetOrigSrc (Mac48Address OrigSrc);
+ Mac48Address GetOrigSrc () const;
+ void SetProtocol (uint16_t protocol);
+ uint16_t GetProtocol () const;
+ ///\}
+private:
+ uint8_t m_cost;
+ uint16_t m_seqno;
+ Mac48Address m_origDst;
+ Mac48Address m_origSrc;
+ uint16_t m_protocol;
+ friend bool operator== (const FlameHeader & a, const FlameHeader & b);
+};
+bool operator== (const FlameHeader & a, const FlameHeader & b);
+} //namespace flame
+} //namespace ns3
+#endif /* FLAME_HEADER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-installer.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "flame-installer.h"
+#include "flame-protocol.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+
+namespace ns3
+{
+using namespace flame;
+NS_OBJECT_ENSURE_REGISTERED (FlameStack);
+TypeId
+FlameStack::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::FlameStack")
+ .SetParent<Object> ()
+ .AddConstructor<FlameStack> ();
+ return tid;
+}
+FlameStack::FlameStack ()
+{
+}
+FlameStack::~FlameStack ()
+{
+}
+void
+FlameStack::DoDispose ()
+{
+}
+bool
+FlameStack::InstallStack (Ptr<MeshPointDevice> mp)
+{
+ Ptr<FlameProtocol> flame = CreateObject<FlameProtocol> ();
+ return flame->Install (mp);
+}
+void
+FlameStack::Report (const Ptr<MeshPointDevice> mp, std::ostream& os)
+{
+ mp->Report (os);
+ // TODO report flame counters
+ Ptr<FlameProtocol> flame = mp->GetObject<FlameProtocol> ();
+ NS_ASSERT (flame != 0);
+ flame->Report (os);
+}
+void
+FlameStack::ResetStats (const Ptr<MeshPointDevice> mp)
+{
+ mp->ResetStats ();
+ // TODO reset flame counters
+ Ptr<FlameProtocol> flame = mp->GetObject<FlameProtocol> ();
+ NS_ASSERT (flame != 0);
+
+ flame->ResetStats ();
+}
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-installer.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef FLAME_STACK_INSTALLER_H
+#define FLAME_STACK_INSTALLER_H
+#include "ns3/mesh-stack-installer.h"
+namespace ns3 {
+/**
+ * \ingroup flame
+ *
+ * \brief FLAME mesh stack (actually single protocol in this stack)
+ */
+class FlameStack : public MeshStack
+{
+ public:
+ static TypeId GetTypeId ();
+ FlameStack ();
+ ~FlameStack ();
+ void DoDispose ();
+
+ /// Installs flame stack on given mesh point device.
+ bool InstallStack (Ptr<MeshPointDevice> mp);
+ void Report (const Ptr<MeshPointDevice> mp, std::ostream&);
+ void ResetStats (const Ptr<MeshPointDevice> mp);
+};
+} //namespace ns3
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-protocol-mac.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,128 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "flame-protocol-mac.h"
+#include "flame-protocol.h"
+#include "flame-header.h"
+#include "ns3/log.h"
+namespace ns3 {
+namespace flame {
+NS_LOG_COMPONENT_DEFINE ("FlameProtocolMac");
+FlameProtocolMac::FlameProtocolMac (uint32_t ifIndex, Ptr<FlameProtocol> protocol) :
+ m_protocol (protocol), m_ifIndex (ifIndex)
+{
+}
+FlameProtocolMac::~FlameProtocolMac ()
+{
+}
+void
+FlameProtocolMac::SetParent (Ptr<MeshWifiInterfaceMac> parent)
+{
+ m_parent = parent;
+}
+
+bool
+FlameProtocolMac::Receive (Ptr<Packet> packet, const WifiMacHeader & header)
+{
+ if (!header.IsData ())
+ {
+ return true;
+ }
+ FlameTag tag;
+ if (packet->PeekPacketTag (tag))
+ {
+ NS_FATAL_ERROR ("FLAME tag is not supposed to be received by network");
+ }
+ tag.receiver = header.GetAddr1 ();
+ tag.transmitter = header.GetAddr2 ();
+ if (tag.receiver == Mac48Address::GetBroadcast ())
+ {
+ m_stats.rxBroadcast++;
+ }
+ else
+ {
+ m_stats.rxUnicast++;
+ }
+ m_stats.rxBytes += packet->GetSize ();
+ packet->AddPacketTag (tag);
+ return true;
+}
+bool
+FlameProtocolMac::UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from,
+ Mac48Address to)
+{
+ if (!header.IsData ())
+ {
+ return true;
+ }
+ FlameTag tag;
+ if (!packet->RemovePacketTag (tag))
+ {
+ NS_FATAL_ERROR ("FLAME tag must exist here");
+ }
+ header.SetAddr1 (tag.receiver);
+ if (tag.receiver == Mac48Address::GetBroadcast ())
+ {
+ m_stats.txBroadcast++;
+ }
+ else
+ {
+ m_stats.txUnicast++;
+ }
+ m_stats.txBytes += packet->GetSize ();
+ return true;
+}
+uint16_t
+FlameProtocolMac::GetChannelId () const
+{
+ return m_parent->GetFrequencyChannel ();
+}
+FlameProtocolMac::Statistics::Statistics () :
+ txUnicast (0), txBroadcast (0), txBytes (0), rxUnicast (0), rxBroadcast (0), rxBytes (0)
+{
+}
+void
+FlameProtocolMac::Statistics::Print (std::ostream &os) const
+{
+ os << "<Statistics "
+ "txUnicast=\"" << txUnicast << "\" "
+ "txBroadcast=\"" << txBroadcast << "\" "
+ "txBytes=\"" << txBytes << "\" "
+ "rxUnicast=\"" << rxUnicast << "\" "
+ "rxBroadcast=\"" << rxBroadcast << "\" "
+ "rxBytes=\"" << rxBytes << "\"/>" << std::endl;
+}
+void
+FlameProtocolMac::Report (std::ostream & os) const
+{
+ os << "<FlameProtocolMac" << std::endl <<
+ "address =\"" << m_parent->GetAddress () << "\">" << std::endl;
+ m_stats.Print (os);
+ os << "</FlameProtocolMac>" << std::endl;
+
+}
+void
+FlameProtocolMac::ResetStats ()
+{
+ m_stats = Statistics ();
+}
+
+} //namespace flame
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-protocol-mac.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef FLAME_PROTOCOL_MAC_H
+#define FLAME_PROTOCOL_MAC_H
+
+#include "ns3/mesh-wifi-interface-mac.h"
+
+namespace ns3 {
+namespace flame {
+class FlameProtocol;
+/**
+ * \ingroup flame
+ *
+ * \brief Interface MAC plugin FLAME routing protocol
+ */
+class FlameProtocolMac : public MeshWifiInterfaceMacPlugin
+{
+public:
+ FlameProtocolMac (uint32_t, Ptr<FlameProtocol>);
+ ~FlameProtocolMac ();
+ ///\name Inherited from MAC plugin
+ //\{
+ void SetParent (Ptr<MeshWifiInterfaceMac> parent);
+ bool Receive (Ptr<Packet> packet, const WifiMacHeader & header);
+ bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to);
+ /// Update beacon is empty, because HWMP does not know anything about beacons
+ void UpdateBeacon (MeshWifiBeacon & beacon) const {};
+ //\}
+ uint16_t GetChannelId () const;
+ /// Report statistics
+ void Report (std::ostream &) const;
+ void ResetStats ();
+private:
+ /**
+ * \name MeshPointDevice parameters:
+ * \{
+ */
+ Ptr<FlameProtocol> m_protocol;
+ uint32_t m_ifIndex;
+ Ptr<MeshWifiInterfaceMac> m_parent;
+ ///\}
+ ///\name Statistics:
+ ///\{
+ struct Statistics
+ {
+ uint16_t txUnicast;
+ uint16_t txBroadcast;
+ uint32_t txBytes;
+ uint16_t rxUnicast;
+ uint16_t rxBroadcast;
+ uint32_t rxBytes;
+
+ void Print (std::ostream & os) const;
+ Statistics ();
+ };
+ Statistics m_stats;
+ ///\}
+
+};
+} //namespace flame
+} //namespace ns3
+#endif /* FLAME_PROTOCOL_MAC_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-protocol.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,375 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#include "flame-protocol.h"
+#include "flame-header.h"
+#include "ns3/llc-snap-header.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/random-variable.h"
+
+NS_LOG_COMPONENT_DEFINE ("FlameProtocol");
+
+namespace ns3 {
+namespace flame {
+//-----------------------------------------------------------------------------
+// FlameTag
+//-----------------------------------------------------------------------------
+NS_OBJECT_ENSURE_REGISTERED (FlameTag);
+
+TypeId
+FlameTag::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::flame::FlameTag") .SetParent<Tag> () .AddConstructor<FlameTag> ();
+ return tid;
+}
+
+TypeId
+FlameTag::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+
+uint32_t
+FlameTag::GetSerializedSize () const
+{
+ return 12;
+}
+
+void
+FlameTag::Serialize (TagBuffer i) const
+{
+ uint8_t buf[6];
+ receiver.CopyTo (buf);
+ for (int j = 0; j < 6; j++)
+ {
+ i.WriteU8 (buf[j]);
+ }
+ transmitter.CopyTo (buf);
+ for (int j = 0; j < 6; j++)
+ {
+ i.WriteU8 (buf[j]);
+ }
+
+}
+
+void
+FlameTag::Deserialize (TagBuffer i)
+{
+ uint8_t buf[6];
+ for (int j = 0; j < 6; j++)
+ {
+ buf[j] = i.ReadU8 ();
+ }
+ receiver.CopyFrom (buf);
+ for (int j = 0; j < 6; j++)
+ {
+ buf[j] = i.ReadU8 ();
+ }
+ transmitter.CopyFrom (buf);
+
+}
+
+void
+FlameTag::Print (std::ostream &os) const
+{
+ os << "receiver = " << receiver << ", transmitter = " << transmitter;
+}
+
+//-----------------------------------------------------------------------------
+// FlameProtocol
+//-----------------------------------------------------------------------------
+TypeId
+FlameProtocol::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::flame::FlameProtocol")
+ .SetParent<MeshL2RoutingProtocol> ()
+ .AddConstructor<FlameProtocol> ()
+ .AddAttribute ( "BroadcastInterval",
+ "How often we must send broadcast packets",
+ TimeValue (Seconds (5)),
+ MakeTimeAccessor (
+ &FlameProtocol::m_broadcastInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "MaxCost",
+ "Cost threshold after which packet will be dropeed",
+ UintegerValue (32),
+ MakeUintegerAccessor (
+ &FlameProtocol::m_maxCost),
+ MakeUintegerChecker<uint8_t> (3)
+ )
+ ;
+ return tid;
+}
+FlameProtocol::FlameProtocol () :
+ m_address (Mac48Address ()), m_broadcastInterval (Seconds (5)), m_lastBroadcast (Simulator::Now ()),
+ m_maxCost (32), m_myLastSeqno (1), m_rtable (CreateObject<FlameRtable> ())
+{
+}
+FlameProtocol::~FlameProtocol ()
+{
+}
+void
+FlameProtocol::DoDispose ()
+{
+}
+bool
+FlameProtocol::RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<const Packet> const_packet, uint16_t protocolType, RouteReplyCallback routeReply)
+{
+ Ptr<Packet> packet = const_packet->Copy ();
+ if (sourceIface == m_mp->GetIfIndex ())
+ {
+ //Packet from upper layer!
+ FlameTag tag;
+ if (packet->PeekPacketTag (tag))
+ {
+ NS_FATAL_ERROR ("FLAME tag is not supposed to be received from upper layers");
+ }
+ FlameRtable::LookupResult result = m_rtable->Lookup (destination);
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ {
+ m_lastBroadcast = Simulator::Now ();
+ }
+ if (m_lastBroadcast + m_broadcastInterval < Simulator::Now ())
+ {
+ result.retransmitter = Mac48Address::GetBroadcast ();
+ result.ifIndex = FlameRtable::INTERFACE_ANY;
+ m_lastBroadcast = Simulator::Now ();
+ }
+ FlameHeader flameHdr;
+ flameHdr.AddCost (0);
+ flameHdr.SetSeqno (m_myLastSeqno++);
+ flameHdr.SetProtocol (protocolType);
+ flameHdr.SetOrigDst (destination);
+ flameHdr.SetOrigSrc (source);
+ m_stats.txBytes += packet->GetSize ();
+ packet->AddHeader (flameHdr);
+ tag.receiver = result.retransmitter;
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ {
+ m_stats.txBroadcast++;
+ }
+ else
+ {
+ m_stats.txUnicast++;
+ }
+ NS_LOG_DEBUG ("Source: send packet with RA = " << tag.receiver);
+ packet->AddPacketTag (tag);
+ routeReply (true, packet, source, destination, FLAME_PROTOCOL, result.ifIndex);
+ }
+ else
+ {
+ FlameHeader flameHdr;
+ packet->RemoveHeader (flameHdr);
+ FlameTag tag;
+
+ if (!packet->RemovePacketTag (tag))
+ {
+ NS_FATAL_ERROR ("FLAME tag must exist here");
+ }
+ if (destination == Mac48Address::GetBroadcast ())
+ {
+ //Broadcast always is forwarded as broadcast!
+ NS_ASSERT (HandleDataFrame (flameHdr.GetSeqno (), source, flameHdr, tag.transmitter, sourceIface));
+ FlameTag tag (Mac48Address::GetBroadcast ());
+ flameHdr.AddCost (1);
+ m_stats.txBytes += packet->GetSize ();
+ packet->AddHeader (flameHdr);
+ packet->AddPacketTag (tag);
+ routeReply (true, packet, source, destination, FLAME_PROTOCOL, FlameRtable::INTERFACE_ANY);
+ m_stats.txBroadcast++;
+ return true;
+ }
+ else
+ {
+ // We check sequence only when forward unicast, because broadcast-checks were done
+ // inside remove routing stuff.
+ if (HandleDataFrame (flameHdr.GetSeqno (), source, flameHdr, tag.transmitter, sourceIface))
+ {
+ return false;
+ }
+ FlameRtable::LookupResult result = m_rtable->Lookup (destination);
+ if (tag.receiver != Mac48Address::GetBroadcast ())
+ {
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ {
+ NS_LOG_DEBUG ("unicast packet dropped, because no route! I am " << GetAddress ()
+ << ", RA = " << tag.receiver << ", TA = " << tag.transmitter);
+ m_stats.totalDropped++;
+ return false;
+ }
+ }
+ tag.receiver = result.retransmitter;
+ if (result.retransmitter == Mac48Address::GetBroadcast ())
+ {
+ m_stats.txBroadcast++;
+ }
+ else
+ {
+ m_stats.txUnicast++;
+ }
+ m_stats.txBytes += packet->GetSize ();
+ flameHdr.AddCost (1);
+ packet->AddHeader (flameHdr);
+ packet->AddPacketTag (tag);
+ routeReply (true, packet, source, destination, FLAME_PROTOCOL, result.ifIndex);
+ return true;
+ }
+ return true;
+ }
+ return false;
+}
+bool
+FlameProtocol::RemoveRoutingStuff (uint32_t fromIface, const Mac48Address source,
+ const Mac48Address destination, Ptr<Packet> packet, uint16_t& protocolType)
+{
+ //Filter seqno:
+ if (source == GetAddress ())
+ {
+ NS_LOG_DEBUG ("Dropped my own frame!");
+ return false;
+ }
+ FlameTag tag;
+ if (!packet->RemovePacketTag (tag))
+ {
+ NS_FATAL_ERROR ("FLAME tag must exist when packet is coming to protocol");
+ }
+ FlameHeader flameHdr;
+ packet->RemoveHeader (flameHdr);
+ if ((destination == GetAddress ()) && (m_lastBroadcast + m_broadcastInterval < Simulator::Now ()))
+ {
+ Ptr<Packet> packet = Create<Packet> ();
+ m_mp->Send(packet, Mac48Address::GetBroadcast (), 0);
+ m_lastBroadcast = Simulator::Now ();
+ }
+ NS_ASSERT (protocolType == FLAME_PROTOCOL);
+ protocolType = flameHdr.GetProtocol ();
+ if ((HandleDataFrame (flameHdr.GetSeqno (), source, flameHdr, tag.transmitter, fromIface))
+ || packet->GetSize () == 0)
+ {
+ return false;
+ }
+ return true;
+}
+bool
+FlameProtocol::Install (Ptr<MeshPointDevice> mp)
+{
+ m_mp = mp;
+ std::vector<Ptr<NetDevice> > interfaces = mp->GetInterfaces ();
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = interfaces.begin (); i != interfaces.end (); i++)
+ {
+ // Checking for compatible net device
+ Ptr<WifiNetDevice> wifiNetDev = (*i)->GetObject<WifiNetDevice> ();
+ if (wifiNetDev == 0)
+ {
+ return false;
+ }
+ Ptr<MeshWifiInterfaceMac> mac = wifiNetDev->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ if (mac == 0)
+ {
+ return false;
+ }
+ // Installing plugins:
+ Ptr<FlameProtocolMac> flameMac = Create<FlameProtocolMac> (wifiNetDev->GetIfIndex (), this);
+ m_interfaces[wifiNetDev->GetIfIndex ()] = flameMac;
+ mac->SetBeaconGeneration (false);
+ mac->InstallPlugin (flameMac);
+ }
+ mp->SetRoutingProtocol (this);
+ // Mesh point aggregates all installed protocols
+ mp->AggregateObject (this);
+ m_address = Mac48Address::ConvertFrom (mp->GetAddress ());//* address;
+ return true;
+}
+Mac48Address
+FlameProtocol::GetAddress ()
+{
+ return m_address;
+}
+bool
+FlameProtocol::HandleDataFrame (uint16_t seqno, Mac48Address source, const FlameHeader flameHdr,
+ Mac48Address receiver, uint32_t fromInterface)
+{
+ if (source == GetAddress ())
+ {
+ m_stats.totalDropped++;
+ return true;
+ }
+ FlameRtable::LookupResult result = m_rtable->Lookup (source);
+ if ((result.retransmitter != Mac48Address::GetBroadcast ()) && ((int16_t)(result.seqnum - seqno) >= 0))
+ {
+ return true;
+ }
+ if (flameHdr.GetCost () > m_maxCost)
+ {
+ m_stats.droppedTtl++;
+ return true;
+ }
+ m_rtable->AddPath (source, receiver, fromInterface, flameHdr.GetCost (), flameHdr.GetSeqno ());
+ return false;
+}
+//Statistics:
+FlameProtocol::Statistics::Statistics () :
+ txUnicast (0), txBroadcast (0), txBytes (0), droppedTtl (0), totalDropped (0)
+{
+}
+void
+FlameProtocol::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ "txUnicast=\"" << txUnicast << "\" "
+ "txBroadcast=\"" << txBroadcast << "\" "
+ "txBytes=\"" << txBytes << "\" "
+ "droppedTtl=\"" << droppedTtl << "\" "
+ "totalDropped=\"" << totalDropped << "\"/>" << std::endl;
+}
+void
+FlameProtocol::Report (std::ostream & os) const
+{
+ os << "<Flame "
+ "address=\"" << m_address << "\"" << std::endl <<
+ "broadcastInterval=\"" << m_broadcastInterval.GetSeconds () << "\"" << std::endl <<
+ "maxCost=\"" << (uint16_t) m_maxCost << "\">" << std::endl;
+ m_stats.Print (os);
+ for (FlamePluginMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin++)
+ {
+ plugin->second->Report (os);
+ }
+ os << "</Flame>" << std::endl;
+}
+void
+FlameProtocol::ResetStats ()
+{
+ m_stats = Statistics ();
+ for (FlamePluginMap::const_iterator plugin = m_interfaces.begin (); plugin != m_interfaces.end (); plugin++)
+ {
+ plugin->second->ResetStats ();
+ }
+}
+
+} //namespace flame
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-protocol.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef FLAME_PROTOCOL_H
+#define FLAME_PROTOCOL_H
+
+#include "flame-protocol-mac.h"
+#include "flame-header.h"
+#include "flame-rtable.h"
+
+#include "ns3/mesh-l2-routing-protocol.h"
+#include "ns3/tag.h"
+#include <map>
+
+/**
+ * \ingroup mesh
+ * \defgroup flame FLAME
+ *
+ * \brief Forwarding LAyer for MEshing protocol
+ *
+ * Simple L2.5 mesh routing protocol developed by
+ * Herman Elfrink <herman.elfrink@ti-wmc.nl> and presented in
+ * "Easy Wireless: broadband ad-hoc networking for emergency services"
+ * by Maurits de Graaf et. al. at The Sixth Annual Mediterranean Ad Hoc
+ * Networking WorkShop, Corfu, Greece, June 12-15, 2007
+ *
+ * see also Linux kernel mailing list discussion at
+ * http://lkml.org/lkml/2006/5/23/82
+ */
+namespace ns3 {
+namespace flame {
+/**
+ * \ingroup flame
+ * \brief Transmitter and receiver addresses
+ */
+class FlameTag : public Tag
+{
+public:
+ /// transmitter for incoming:
+ Mac48Address transmitter;
+ /// Receiver of the packet:
+ Mac48Address receiver;
+
+ FlameTag (Mac48Address a = Mac48Address ()) :
+ receiver (a){}
+
+ ///\name Inherited from Tag
+ //\{
+ static TypeId GetTypeId ();
+ TypeId GetInstanceTypeId () const;
+ uint32_t GetSerializedSize () const;
+ void Serialize (TagBuffer i) const;
+ void Deserialize (TagBuffer i);
+ void Print (std::ostream &os) const;
+ //\}
+};
+
+/**
+ * \ingroup flame
+ * \brief FLAME routing protocol
+ */
+class FlameProtocol : public MeshL2RoutingProtocol
+{
+public:
+ static TypeId GetTypeId ();
+ FlameProtocol ();
+ ~FlameProtocol ();
+ void DoDispose ();
+
+ /// Route request, inherited from MeshL2RoutingProtocol
+ bool RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination,
+ Ptr<const Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply);
+ /// Cleanup flame headers!
+ bool RemoveRoutingStuff (uint32_t fromIface, const Mac48Address source,
+ const Mac48Address destination, Ptr<Packet> packet, uint16_t& protocolType);
+ /**
+ * \brief Install FLAME on given mesh point.
+ *
+ * Installing protocol cause installing its interface MAC plugins.
+ *
+ * Also MP aggregates all installed protocols, FLAME protocol can be accessed
+ * via MeshPointDevice::GetObject<flame::FlameProtocol>();
+ */
+ bool Install (Ptr<MeshPointDevice>);
+ Mac48Address GetAddress ();
+ /// Statistics
+ void Report (std::ostream &) const;
+ void ResetStats ();
+private:
+ /// LLC protocol number reserved by flame
+ static const uint16_t FLAME_PROTOCOL = 0x4040;
+ /**
+ * \brief Handles a packet: adds a routing information and drops packets by TTL or Seqno
+ *
+ * \return true if packet shall be dropped
+ */
+ bool HandleDataFrame (uint16_t seqno, Mac48Address source, const FlameHeader flameHdr, Mac48Address receiver, uint32_t fromIface);
+ /**
+ * \name Information about MeshPointDeviceaddress, plugins
+ * \{
+ */
+ typedef std::map<uint32_t, Ptr<FlameProtocolMac> > FlamePluginMap;
+ FlamePluginMap m_interfaces;
+ Mac48Address m_address;
+ //\}
+ /**
+ * \name Broadcast timers:
+ * \{
+ */
+ Time m_broadcastInterval;
+ Time m_lastBroadcast;
+ //\}
+ /// Max Cost value (or TTL, because cost is actually hopcount)
+ uint8_t m_maxCost;
+ /// Sequence number:
+ uint16_t m_myLastSeqno;
+ /// Routing table:
+ Ptr<FlameRtable> m_rtable;
+ ///\name Statistics:
+ ///\{
+ struct Statistics
+ {
+ uint16_t txUnicast;
+ uint16_t txBroadcast;
+ uint32_t txBytes;
+ uint16_t droppedTtl;
+ uint16_t totalDropped;
+ void Print (std::ostream & os) const;
+ Statistics ();
+ };
+ Statistics m_stats;
+ ///\}
+
+};
+} //namespace flame
+} //namespace ns3
+#endif /* FLAME_PROTOCOL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-rtable.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,193 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+#include "ns3/assert.h"
+#include "ns3/simulator.h"
+#include "ns3/test.h"
+#include "ns3/log.h"
+
+#include "flame-rtable.h"
+namespace ns3 {
+namespace flame {
+
+NS_LOG_COMPONENT_DEFINE ("FlameRtable");
+
+NS_OBJECT_ENSURE_REGISTERED (FlameRtable);
+
+TypeId
+FlameRtable::GetTypeId ()
+{
+ static TypeId tid =
+ TypeId ("ns3::flame::FlameRtable")
+ .SetParent<Object> () .AddConstructor<FlameRtable> ()
+ .AddAttribute ( "Lifetime",
+ "The lifetime of the routing enrty",
+ TimeValue (Seconds (120)), MakeTimeAccessor (
+ &FlameRtable::m_lifetime),
+ MakeTimeChecker ()
+ )
+ ;
+ return tid;
+}
+FlameRtable::FlameRtable () :
+ m_lifetime (Seconds (120))
+{
+}
+FlameRtable::~FlameRtable ()
+{
+}
+void
+FlameRtable::DoDispose ()
+{
+ m_routes.clear ();
+}
+void
+FlameRtable::AddPath (const Mac48Address destination, const Mac48Address retransmitter,
+ const uint32_t interface, const uint8_t cost, const uint16_t seqnum)
+{
+ std::map<Mac48Address, Route>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ {
+ Route newroute;
+ newroute.cost = cost;
+ newroute.retransmitter = retransmitter;
+ newroute.interface = interface;
+ newroute.whenExpire = Simulator::Now () + m_lifetime;
+ newroute.seqnum = seqnum;
+ m_routes[destination] = newroute;
+ return;
+ }
+ i->second.seqnum = seqnum;
+ NS_ASSERT (i != m_routes.end ());
+ i->second.retransmitter = retransmitter;
+ i->second.interface = interface;
+ i->second.cost = cost;
+ i->second.whenExpire = Simulator::Now () + m_lifetime;
+}
+FlameRtable::LookupResult
+FlameRtable::Lookup (Mac48Address destination)
+{
+ std::map<Mac48Address, Route>::iterator i = m_routes.find (destination);
+ if (i == m_routes.end ())
+ {
+ return LookupResult ();
+ }
+ if ((i->second.whenExpire < Simulator::Now ()))
+ {
+ NS_LOG_DEBUG ("Route has expired, sorry.");
+ m_routes.erase (i);
+ return LookupResult ();
+ }
+ return LookupResult (i->second.retransmitter, i->second.interface, i->second.cost, i->second.seqnum);
+}
+bool
+FlameRtable::LookupResult::operator== (const FlameRtable::LookupResult & o) const
+{
+ return (retransmitter == o.retransmitter && ifIndex == o.ifIndex && cost == o.cost && seqnum == o.seqnum);
+}
+
+bool
+FlameRtable::LookupResult::IsValid () const
+{
+ return !(retransmitter == Mac48Address::GetBroadcast () && ifIndex == INTERFACE_ANY && cost == MAX_COST
+ && seqnum == 0);
+}
+
+#ifdef RUN_SELF_TESTS
+/// Unit test for FlameRtable
+class FlameRtableTest : public Test
+{
+public:
+ FlameRtableTest ();
+ virtual bool
+ RunTests ();
+
+private:
+ /// Test Add apth and lookup path;
+ void
+ TestLookup ();
+ /**
+ * \name Test add path and try to lookup after entry has expired
+ * \{
+ */
+ void
+ TestAddPath ();
+ void
+ TestExpire ();
+ ///\}
+private:
+ bool result;
+
+ Mac48Address dst;
+ Mac48Address hop;
+ uint32_t iface;
+ uint8_t cost;
+ uint16_t seqnum;
+ Ptr<FlameRtable> table;
+};
+
+/// Test instance
+static FlameRtableTest g_FlameRtableTest;
+
+FlameRtableTest::FlameRtableTest () :
+ Test ("Mesh/Flame/FlameRtable"), result (true), dst ("01:00:00:01:00:01"), hop ("01:00:00:01:00:03"),
+ iface (8010), cost (10), seqnum (1)
+{
+}
+
+void
+FlameRtableTest::TestLookup ()
+{
+ FlameRtable::LookupResult correct (hop, iface, cost, seqnum);
+
+ table->AddPath (dst, hop, iface, cost, seqnum);
+ NS_TEST_ASSERT (table->Lookup (dst) == correct);
+}
+
+void
+FlameRtableTest::TestAddPath ()
+{
+ table->AddPath (dst, hop, iface, cost, seqnum);
+}
+
+void
+FlameRtableTest::TestExpire ()
+{
+ // this is assumed to be called when path records are already expired
+ FlameRtable::LookupResult correct (hop, iface, cost, seqnum);
+ NS_TEST_ASSERT (!table->Lookup (dst).IsValid ());
+}
+bool
+FlameRtableTest::RunTests ()
+{
+ table = CreateObject<FlameRtable> ();
+
+ Simulator::Schedule (Seconds (0), &FlameRtableTest::TestLookup, this);
+ Simulator::Schedule (Seconds (1), &FlameRtableTest::TestAddPath, this);
+ Simulator::Schedule (Seconds (122), &FlameRtableTest::TestExpire, this);
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+} //namespace flame
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/flame-rtable.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,103 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef FLAME_RTABLE_H
+#define FLAME_RTABLE_H
+
+#include <map>
+#include "ns3/nstime.h"
+#include "ns3/object.h"
+#include "ns3/mac48-address.h"
+
+namespace ns3 {
+namespace flame {
+/**
+ * \ingroup flame
+ *
+ * \brief Routing table for FLAME
+ */
+class FlameRtable : public Object
+{
+public:
+ /// Means all interfaces
+ const static uint32_t INTERFACE_ANY = 0xffffffff;
+ /// Maximum (the best?) path cost
+ const static uint32_t MAX_COST = 0xff;
+
+ /// Route lookup result, return type of LookupXXX methods
+ struct LookupResult
+ {
+ Mac48Address retransmitter;
+ uint32_t ifIndex;
+ uint8_t cost;
+ uint16_t seqnum;
+ LookupResult (Mac48Address r = Mac48Address::GetBroadcast (),
+ uint32_t i = INTERFACE_ANY,
+ uint8_t c = MAX_COST,
+ uint16_t s = 0)
+ : retransmitter (r),
+ ifIndex (i),
+ cost (c),
+ seqnum (s)
+ {
+ }
+ /// True for valid route
+ bool IsValid () const;
+ /// Compare route lookup results, used by tests
+ bool operator==(const LookupResult & o) const;
+ };
+public:
+ static TypeId GetTypeId ();
+ FlameRtable ();
+ ~FlameRtable ();
+ void DoDispose ();
+
+ /// Add path
+ void AddPath (
+ const Mac48Address destination,
+ const Mac48Address retransmitter,
+ const uint32_t interface,
+ const uint8_t cost,
+ const uint16_t seqnum
+ );
+ /**
+ * \brief Lookup path to destination
+ * \return Broadcast if not found
+ */
+ LookupResult Lookup (Mac48Address destination);
+private:
+ /// Routing table entry
+ struct Route
+ {
+ Mac48Address retransmitter;
+ uint32_t interface;
+ uint32_t cost;
+ Time whenExpire;
+ uint32_t seqnum;
+ };
+ /// Lifetime parameter
+ Time m_lifetime;
+ /// List of routes
+ std::map<Mac48Address, Route> m_routes;
+};
+
+} //namespace flame
+} //namespace ns3
+#endif /* FLAME_PROTOCOL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/flame/wscript Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,16 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_module('flame', ['mesh'])
+ obj.source = [
+ 'flame-header.cc',
+ 'flame-rtable.cc',
+ 'flame-protocol-mac.cc',
+ 'flame-protocol.cc',
+ 'flame-installer.cc',
+ ]
+ headers = bld.new_task_gen('ns3header')
+ headers.module = 'flame'
+ headers.source = [
+ 'flame-protocol.h',
+ ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-l2-routing-protocol.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/log.h"
+#include "ns3/mesh-l2-routing-protocol.h"
+#include "ns3/mesh-point-device.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshL2RoutingProtocol");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshL2RoutingProtocol);
+
+TypeId
+MeshL2RoutingProtocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::MeshL2RoutingProtocol")
+ .SetParent<Object> ();
+ return tid;
+}
+
+MeshL2RoutingProtocol::~MeshL2RoutingProtocol ()
+{
+}
+
+void
+MeshL2RoutingProtocol::SetMeshPoint (Ptr<MeshPointDevice> mp)
+{
+ m_mp = mp;
+}
+
+Ptr<MeshPointDevice>
+MeshL2RoutingProtocol::GetMeshPoint () const
+{
+ return m_mp;
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-l2-routing-protocol.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESH_L2_ROUTING_PROTOCOL_H
+#define MESH_L2_ROUTING_PROTOCOL_H
+
+#include "ns3/object.h"
+#include "ns3/mac48-address.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+
+class Packet;
+class MeshPointDevice;
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Interface for L2 mesh routing protocol and mesh point communication.
+ *
+ * Every mesh routing protocol must implement this interface. Each mesh point (MeshPointDevice) is supposed
+ * to know single L2RoutingProtocol to work with, see MeshPointDevice::SetRoutingProtocol ().
+ *
+ * This interface is similar to ipv4 routiong protocol base class.
+ */
+class MeshL2RoutingProtocol : public Object
+{
+public:
+ /// Never forget to support NS3 object model
+ static TypeId GetTypeId ();
+ /// virtual D-tor for subclasses
+ virtual ~MeshL2RoutingProtocol ();
+ /**
+ * Callback to be invoked when route discovery procedure is completed.
+ *
+ * \param flag indicating whether a route was actually found and all needed information is
+ * added to the packet succesfully
+ *
+ * \param packet for which the route was resolved. All routing information for MAC layer
+ * must be stored in proper tags (like in case of HWMP, when WifiMacHeader
+ * needs address of next hop), or must be added as a packet header (if MAC
+ * does not need any additional information). So, the packet is returned back
+ * to MeshPointDevice looks like a pure packet with ethernet header
+ * (i.e data + src +dst + protocol). The only special information addressed
+ * to MeshPointDevice is an outcoming interface ID.
+ *
+ * \param src source address of the packet
+ *
+ * \param dst destiation address of the packet
+ *
+ * \param protocol ethernet 'Protocol' field, needed to form a proper MAC-layer header
+ *
+ * \param uint32_t outcoming interface to use or 0xffffffff if packet should be sent by ALL interfaces
+ */
+ typedef Callback<void,/* return type */
+ bool, /* flag */
+ Ptr<Packet>, /* packet */
+ Mac48Address,/* src */
+ Mac48Address,/* dst */
+ uint16_t, /* protocol */
+ uint32_t /* out interface ID */
+ > RouteReplyCallback;
+ /**
+ * Request routing information, all packets must go through this request.
+ *
+ * Note that route discovery works async. -- RequestRoute returns immediately, while
+ * reply callback will be called when routing information will be available.
+ * \return true if valid route is already known
+ * \param sourceIface the incoming interface of the packet
+ * \param source source address
+ * \param destination destination address
+ * \param packet the packet to be resolved (needed the whole packet, because
+ * routing information is added as tags or headers). The packet
+ * will be returned to reply callback.
+ * \param protocolType protocol ID, needed to form a proper MAC-layer header
+ * \param routeReply callback to be invoked after route discovery procedure, supposed
+ * to really send packet using routing information.
+ */
+ virtual bool RequestRoute (uint32_t sourceIface, const Mac48Address source, const Mac48Address destination, Ptr<
+ const Packet> packet, uint16_t protocolType, RouteReplyCallback routeReply) = 0;
+ /**
+ * \brief When packet is ready to go to upper layer, protocol must
+ * remove all its information: tags, header, etc. So,
+ * MeshPointDevice must call this method when passing a packet to
+ * upper layer.
+ * \returns true if packet shall not be dropeed, false otherwise.
+ * \param sourceIface the incoming interface of the packet
+ * \param source source address
+ * \param destination destination address
+ * \param packet the packet to be handled
+ * \param protocolType protocol ID, needed to form a proper MAC-layer header
+ * \attention protocol type is passed by reference, because may be
+ * changed
+ */
+ virtual bool RemoveRoutingStuff (uint32_t fromIface, const Mac48Address source, const Mac48Address destination, Ptr<
+ Packet> packet, uint16_t & protocolType) = 0;
+ /// Set host mesh point, analog of SetNode (...) methods for upper layer protocols.
+ void
+ SetMeshPoint (Ptr<MeshPointDevice> mp);
+ /// Each mesh protocol must be installed on the mesh point to work.
+ Ptr<MeshPointDevice>
+ GetMeshPoint () const;
+protected:
+ /// Host mesh point
+ Ptr<MeshPointDevice> m_mp;
+};
+}//namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-point-device.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,462 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshPointDevice");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshPointDevice);
+
+TypeId
+MeshPointDevice::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::MeshPointDevice")
+ .SetParent<NetDevice> ()
+ .AddConstructor<MeshPointDevice> ()
+ .AddAttribute ( "RoutingProtocol",
+ "The mesh routing protocol used by this mesh point.",
+ PointerValue (),
+ MakePointerAccessor (
+ &MeshPointDevice::GetRoutingProtocol, &MeshPointDevice::SetRoutingProtocol),
+ MakePointerChecker<
+ MeshL2RoutingProtocol> ());
+ return tid;
+}
+
+MeshPointDevice::MeshPointDevice () :
+ m_ifIndex (0), m_mtu (1500)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_channel = CreateObject<BridgeChannel> ();
+}
+
+MeshPointDevice::~MeshPointDevice ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+MeshPointDevice::DoDispose ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ for (std::vector<Ptr<NetDevice> >::iterator iter = m_ifaces.begin (); iter != m_ifaces.end (); iter++)
+ {
+ *iter = 0;
+ }
+ m_ifaces.clear ();
+ m_node = 0;
+ NetDevice::DoDispose ();
+
+}
+
+//-----------------------------------------------------------------------------
+// NetDevice interface implementation
+//-----------------------------------------------------------------------------
+
+void
+MeshPointDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet, uint16_t protocol,
+ Address const &src, Address const &dst, PacketType packetType)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_LOG_DEBUG ("UID is " << packet->GetUid ());
+ const Mac48Address src48 = Mac48Address::ConvertFrom (src);
+ const Mac48Address dst48 = Mac48Address::ConvertFrom (dst);
+ uint16_t& realProtocol = protocol;
+ NS_LOG_DEBUG ("SRC=" << src48 << ", DST = " << dst48 << ", I am: " << m_address);
+ if (!m_promiscRxCallback.IsNull ())
+ {
+ m_promiscRxCallback (this, packet, protocol, src, dst, packetType);
+ }
+ if (dst48.IsGroup ())
+ {
+ Ptr<Packet> packet_copy = packet->Copy ();
+ if (m_routingProtocol->RemoveRoutingStuff (incomingPort->GetIfIndex (), src48, dst48, packet_copy, realProtocol))
+ {
+ m_rxCallback (this, packet_copy, realProtocol, src);
+ Forward (incomingPort, packet, protocol, src48, dst48);
+
+ m_rxStats.broadcastData++;
+ m_rxStats.broadcastDataBytes += packet->GetSize ();
+ }
+ return;
+ }
+ if (dst48 == m_address)
+ {
+ Ptr<Packet> packet_copy = packet->Copy ();
+ if (m_routingProtocol->RemoveRoutingStuff (incomingPort->GetIfIndex (), src48, dst48, packet_copy, realProtocol))
+ {
+ m_rxCallback (this, packet_copy, realProtocol, src);
+ m_rxStats.unicastData++;
+ m_rxStats.unicastDataBytes += packet->GetSize ();
+ }
+ return;
+ }
+ else
+ Forward (incomingPort, packet->Copy (), protocol, src48, dst48);
+}
+
+void
+MeshPointDevice::Forward (Ptr<NetDevice> inport, Ptr<const Packet> packet, uint16_t protocol,
+ const Mac48Address src, const Mac48Address dst)
+{
+ // pass through routing protocol
+ m_routingProtocol->RequestRoute (inport->GetIfIndex (), src, dst, packet, protocol, MakeCallback (
+ &MeshPointDevice::DoSend, this));
+}
+
+void
+MeshPointDevice::SetIfIndex (const uint32_t index)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_ifIndex = index;
+}
+
+uint32_t
+MeshPointDevice::GetIfIndex () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_ifIndex;
+}
+
+Ptr<Channel>
+MeshPointDevice::GetChannel () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_channel;
+}
+
+Address
+MeshPointDevice::GetAddress () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_address;
+}
+
+void
+MeshPointDevice::SetAddress (Address a)
+{
+ NS_LOG_WARN ("Manual changing mesh point address can cause routing errors.");
+ m_address = Mac48Address::ConvertFrom (a);
+}
+
+bool
+MeshPointDevice::SetMtu (const uint16_t mtu)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_mtu = mtu;
+ return true;
+}
+
+uint16_t
+MeshPointDevice::GetMtu () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_mtu;
+}
+
+bool
+MeshPointDevice::IsLinkUp () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+void
+MeshPointDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+ // do nothing
+}
+
+bool
+MeshPointDevice::IsBroadcast () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+Address
+MeshPointDevice::GetBroadcast () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+
+bool
+MeshPointDevice::IsMulticast () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+Address
+MeshPointDevice::GetMulticast (Ipv4Address multicastGroup) const
+{
+ NS_LOG_FUNCTION (this << multicastGroup);
+ Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
+ return multicast;
+}
+
+bool
+MeshPointDevice::IsPointToPoint () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return false;
+}
+
+bool
+MeshPointDevice::IsBridge () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return false;
+}
+
+bool
+MeshPointDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+ const Mac48Address dst48 = Mac48Address::ConvertFrom (dest);
+ return m_routingProtocol->RequestRoute (m_ifIndex, m_address, dst48, packet, protocolNumber, MakeCallback (
+ &MeshPointDevice::DoSend, this));
+}
+
+bool
+MeshPointDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest,
+ uint16_t protocolNumber)
+{
+ const Mac48Address src48 = Mac48Address::ConvertFrom (src);
+ const Mac48Address dst48 = Mac48Address::ConvertFrom (dest);
+ return m_routingProtocol->RequestRoute (m_ifIndex, src48, dst48, packet, protocolNumber, MakeCallback (
+ &MeshPointDevice::DoSend, this));
+}
+
+Ptr<Node>
+MeshPointDevice::GetNode () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_node;
+}
+
+void
+MeshPointDevice::SetNode (Ptr<Node> node)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_node = node;
+}
+
+bool
+MeshPointDevice::NeedsArp () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return true;
+}
+
+void
+MeshPointDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_rxCallback = cb;
+}
+
+void
+MeshPointDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_promiscRxCallback = cb;
+}
+
+bool
+MeshPointDevice::SupportsSendFrom () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return false; // don't allow to bridge mesh network with something else.
+}
+
+Address
+MeshPointDevice::GetMulticast (Ipv6Address addr) const
+{
+ NS_LOG_FUNCTION (this << addr);
+ return Mac48Address::GetMulticast (addr);
+}
+
+//-----------------------------------------------------------------------------
+// Interfaces
+//-----------------------------------------------------------------------------
+uint32_t
+MeshPointDevice::GetNInterfaces () const
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ return m_ifaces.size ();
+}
+
+Ptr<NetDevice>
+MeshPointDevice::GetInterface (uint32_t n) const
+{
+ for (std::vector<Ptr<NetDevice> >::const_iterator i = m_ifaces.begin (); i != m_ifaces.end (); i++)
+ {
+ if ((*i)->GetIfIndex () == n)
+ {
+ return (*i);
+ }
+ }
+ NS_FATAL_ERROR ("Mesh point interface is not found by index");
+ return 0;
+}
+std::vector<Ptr<NetDevice> >
+MeshPointDevice::GetInterfaces () const
+{
+ return m_ifaces;
+}
+void
+MeshPointDevice::AddInterface (Ptr<NetDevice> iface)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ NS_ASSERT (iface != this);
+ if (!Mac48Address::IsMatchingType (iface->GetAddress ()))
+ {
+ NS_FATAL_ERROR ("Device does not support eui 48 addresses: cannot be used as a mesh point interface.");
+ }
+ if (!iface->SupportsSendFrom ())
+ {
+ NS_FATAL_ERROR ("Device does not support SendFrom: cannot be used as a mesh point interface.");
+ }
+
+ // Mesh point has MAC address of it's first interface
+ if (m_ifaces.empty ())
+ {
+ m_address = Mac48Address::ConvertFrom (iface->GetAddress ());
+ }
+ Ptr<WifiNetDevice> wifiNetDev = iface->GetObject<WifiNetDevice> ();
+ if (wifiNetDev == 0)
+ {
+ NS_FATAL_ERROR ("Device is not a WiFi NIC: cannot be used as a mesh point interface.");
+ }
+ Ptr<MeshWifiInterfaceMac> ifaceMac = wifiNetDev->GetMac ()->GetObject<MeshWifiInterfaceMac> ();
+ if (ifaceMac == 0)
+ {
+ NS_FATAL_ERROR (
+ "WiFi device doesn't have correct MAC installed: cannot be used as a mesh point interface.");
+ }
+ ifaceMac->SetMeshPointAddress (m_address);
+
+ // Receive frames from this interface
+ m_node->RegisterProtocolHandler (MakeCallback (&MeshPointDevice::ReceiveFromDevice, this), 0, iface, /*promiscuous = */
+ true);
+ m_ifaces.push_back (iface);
+ m_channel->AddChannel (iface->GetChannel ());
+}
+
+//-----------------------------------------------------------------------------
+// Protocols
+//-----------------------------------------------------------------------------
+
+void
+MeshPointDevice::SetRoutingProtocol (Ptr<MeshL2RoutingProtocol> protocol)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ NS_ASSERT_MSG (PeekPointer (protocol->GetMeshPoint ()) == this,
+ "Routing protocol must be installed on mesh point to be useful.");
+ m_routingProtocol = protocol;
+}
+
+Ptr<MeshL2RoutingProtocol>
+MeshPointDevice::GetRoutingProtocol () const
+{
+ return m_routingProtocol;
+}
+
+void
+MeshPointDevice::DoSend (bool success, Ptr<Packet> packet, Mac48Address src, Mac48Address dst,
+ uint16_t protocol, uint32_t outIface)
+{
+ if (!success)
+ {
+ NS_LOG_DEBUG ("Resolve failed");
+ return;
+ }
+
+ // Count statistics
+ Statistics * stats = ((src == m_address) ? &m_txStats : &m_fwdStats);
+
+ if (dst.IsBroadcast ())
+ {
+ stats->broadcastData++;
+ stats->broadcastDataBytes += packet->GetSize ();
+ }
+ else
+ {
+ stats->unicastData++;
+ stats->unicastDataBytes += packet->GetSize ();
+ }
+
+ // Send
+ if (outIface != 0xffffffff)
+ {
+ GetInterface (outIface)->SendFrom (packet, src, dst, protocol);
+ }
+ else
+ {
+ for (std::vector<Ptr<NetDevice> >::iterator i = m_ifaces.begin (); i != m_ifaces.end (); i++)
+ {
+ (*i) -> SendFrom (packet->Copy (), src, dst, protocol);
+ }
+ }
+}
+MeshPointDevice::Statistics::Statistics () :
+ unicastData (0), unicastDataBytes (0), broadcastData (0), broadcastDataBytes (0)
+{
+}
+
+void
+MeshPointDevice::Report (std::ostream & os) const
+{
+ os << "<Statistics" << std::endl <<
+ "txUnicastData=\"" << m_txStats.unicastData << "\"" << std::endl <<
+ "txUnicastDataBytes=\"" << m_txStats.unicastDataBytes << "\"" << std::endl <<
+ "txBroadcastData=\"" << m_txStats.broadcastData << "\"" << std::endl <<
+ "txBroadcastDataBytes=\"" << m_txStats.broadcastDataBytes << "\"" << std::endl <<
+ "rxUnicastData=\"" << m_rxStats.unicastData << "\"" << std::endl <<
+ "rxUnicastDataBytes=\"" << m_rxStats.unicastDataBytes << "\"" << std::endl <<
+ "rxBroadcastData=\"" << m_rxStats.broadcastData << "\"" << std::endl <<
+ "rxBroadcastDataBytes=\"" << m_rxStats.broadcastDataBytes << "\"" << std::endl <<
+ "fwdUnicastData=\"" << m_fwdStats.unicastData << "\"" << std::endl <<
+ "fwdUnicastDataBytes=\"" << m_fwdStats.unicastDataBytes << "\"" << std::endl <<
+ "fwdBroadcastData=\"" << m_fwdStats.broadcastData << "\"" << std::endl <<
+ "fwdBroadcastDataBytes=\"" << m_fwdStats.broadcastDataBytes << "\"" << std::endl <<
+ "/>" << std::endl;
+}
+
+void
+MeshPointDevice::ResetStats ()
+{
+ m_rxStats = Statistics ();
+ m_txStats = Statistics ();
+ m_fwdStats = Statistics ();
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-point-device.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef L2ROUTING_NET_DEVICE_H
+#define L2ROUTING_NET_DEVICE_H
+
+#include "ns3/net-device.h"
+#include "ns3/mac48-address.h"
+#include "ns3/bridge-channel.h"
+#include "ns3/mesh-l2-routing-protocol.h"
+
+namespace ns3 {
+
+class Node;
+/**
+ * \ingroup mesh
+ *
+ * \brief Virtual net device modeling mesh point.
+ *
+ * Mesh point is a virtual net device which is responsible for
+ * - Aggreagating and coordinating 1..* real devices -- mesh interfaces, see MeshInterfaceDevice class.
+ * - Hosting all mesh-related level 2 protocols.
+ *
+ * One of hosted L2 protocols must inplement L2RoutingProtocol interface and is used for packets forwarding.
+ *
+ * From the level 3 point of view MeshPointDevice is similar to BridgeNetDevice, but the packets,
+ * which going through may be changed (because L2 protocols may require their own headers or tags).
+ *
+ * Attributes: TODO
+ */
+class MeshPointDevice : public NetDevice
+{
+public:
+ /// Object type ID for NS3 object system
+ static TypeId GetTypeId ();
+ /// C-tor create empty (without interfaces and protocols) mesh point
+ MeshPointDevice ();
+ /// D-tor
+ virtual ~MeshPointDevice ();
+
+ ///\name Interfaces
+ //\{
+ /**
+ * \brief Attach new interface to the station. Interface must support 48-bit MAC address and SendFrom method.
+ *
+ * \attention Only MeshPointDevice can have IP address, but not individual interfaces.
+ */
+ void AddInterface (Ptr<NetDevice> port);
+ /**
+ * \return number of interfaces
+ */
+ uint32_t GetNInterfaces () const;
+ /**
+ * \return interface device by its index (aka ID)
+ * \param id is interface id, 0 <= id < GetNInterfaces
+ */
+ Ptr<NetDevice> GetInterface (uint32_t id) const;
+ /**
+ * \return vector of interfaces
+ */
+ std::vector<Ptr<NetDevice> > GetInterfaces () const;
+ //\}
+
+ ///\name Protocols
+ //\{
+ /// Register routing protocol to be used. Protocol must be alredy installed on this mesh point.
+ void SetRoutingProtocol (Ptr<MeshL2RoutingProtocol> protocol);
+ /// Access current routing protocol
+ Ptr<MeshL2RoutingProtocol> GetRoutingProtocol () const;
+ //\}
+
+ ///\name NetDevice interface for upper layers
+ //\{
+ virtual void SetIfIndex (const uint32_t index);
+ virtual uint32_t GetIfIndex () const;
+ virtual Ptr<Channel> GetChannel () const;
+ virtual Address GetAddress () const;
+ virtual void SetAddress (Address a);
+ virtual bool SetMtu (const uint16_t mtu);
+ virtual uint16_t GetMtu () const;
+ virtual bool IsLinkUp () const;
+ virtual void SetLinkChangeCallback (Callback<void> callback);
+ virtual bool IsBroadcast () const;
+ virtual Address GetBroadcast () const;
+ virtual bool IsMulticast () const;
+ virtual Address GetMulticast (Ipv4Address multicastGroup) const;
+ virtual bool IsPointToPoint () const;
+ virtual bool IsBridge () const;
+ virtual bool Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+ virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
+ virtual Ptr<Node> GetNode () const;
+ virtual void SetNode (Ptr<Node> node);
+ virtual bool NeedsArp () const;
+ virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+ virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
+ virtual bool SupportsSendFrom () const;
+ virtual Address GetMulticast (Ipv6Address addr) const;
+ virtual void DoDispose ();
+ //\}
+
+ ///\name Statistics
+ //\{
+ /// Print statistics counters
+ void Report (std::ostream & os) const;
+ /// Reset statistics counters
+ void ResetStats ();
+ //\}
+
+private:
+ /// Receive packet from interface
+ void ReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
+ Address const &source, Address const &destination, PacketType packetType);
+ /// Forward packet down to interfaces
+ void Forward (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet,
+ uint16_t protocol, const Mac48Address src,
+ const Mac48Address dst);
+ /**
+ * Response callback for L2 routing protocol. This will be executed when routing information is ready.
+ *
+ * \param success True is route found. TODO: diagnose routing errors
+ * \param packet Packet to send
+ * \param src Source MAC address
+ * \param dst Destination MAC address
+ * \param protocol Protocol ID
+ * \param outIface Interface to use (ID) for send (decided by routing protocol). All interfaces will be used if outIface = 0xffffffff
+ */
+ void
+ DoSend (bool success, Ptr<Packet> packet, Mac48Address src, Mac48Address dst, uint16_t protocol,
+ uint32_t iface);
+
+private:
+ /// Receive action
+ NetDevice::ReceiveCallback m_rxCallback;
+ /// Promisc receive action
+ NetDevice::PromiscReceiveCallback m_promiscRxCallback;
+ /// Mesh point MAC address, supposed to be the address of the first added interface
+ Mac48Address m_address;
+ /// Parent node
+ Ptr<Node> m_node;
+ /// List of interfaces
+ std::vector< Ptr<NetDevice> > m_ifaces;
+ /// If index
+ uint32_t m_ifIndex;
+ /// MTU in bytes
+ uint16_t m_mtu;
+ /// Virtual channel for upper layers
+ Ptr<BridgeChannel> m_channel;
+ /// Current routing protocol, used mainly by GetRoutingProtocol
+ Ptr<MeshL2RoutingProtocol> m_routingProtocol;
+
+ /// Device statistics counters
+ struct Statistics
+ {
+ uint32_t unicastData;
+ uint32_t unicastDataBytes;
+ uint32_t broadcastData;
+ uint32_t broadcastDataBytes;
+
+ Statistics ();
+ };
+ /// Counters
+ Statistics m_rxStats, m_txStats, m_fwdStats;
+};
+} //namespace ns3
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-stack-installer.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef MESH_STACK_INSTALLER_H
+#define MESH_STACK_INSTALLER_H
+#include "ns3/mesh-point-device.h"
+namespace ns3 {
+/**
+ * \ingroup mesh
+ *
+ * \brief Prototype for class, which helps to install mesh stack of
+ * protocols
+ */
+class MeshStack : public Object
+{
+ public:
+ ///\brief Installs mesh stack. needed by helper only
+ virtual bool InstallStack (Ptr<MeshPointDevice> mp) = 0;
+ virtual void Report (const Ptr<MeshPointDevice> mp, std::ostream&) = 0;
+ virtual void ResetStats (const Ptr<MeshPointDevice> mp) = 0;
+};
+}
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-beacon.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/mesh-wifi-beacon.h"
+
+
+namespace ns3 {
+
+MeshWifiBeacon::MeshWifiBeacon (Ssid ssid, SupportedRates rates, uint64_t us)
+{
+ m_header.SetSsid (ssid);
+ m_header.SetSupportedRates (rates);
+ m_header.SetBeaconIntervalUs (us);
+}
+void
+MeshWifiBeacon::AddInformationElement (Ptr<WifiInformationElement> ie)
+{
+ m_elements.AddInformationElement (ie);
+}
+
+
+Ptr<Packet>
+MeshWifiBeacon::CreatePacket ()
+{
+ Ptr<Packet> packet = Create <Packet> ();
+ packet->AddHeader (m_elements);
+ packet->AddHeader (BeaconHeader ());
+ return packet;
+}
+WifiMacHeader
+MeshWifiBeacon::CreateHeader (Mac48Address address, Mac48Address mpAddress)
+{
+ WifiMacHeader hdr;
+
+ hdr.SetBeacon ();
+ hdr.SetAddr1 (Mac48Address::GetBroadcast ());
+ hdr.SetAddr2 (address);
+ hdr.SetAddr3 (mpAddress);
+ hdr.SetDsNotFrom ();
+ hdr.SetDsNotTo ();
+
+ return hdr;
+}
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-beacon.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIBEACON_H_
+#define MESHWIFIBEACON_H_
+
+#include "ns3/object.h"
+#include "ns3/packet.h"
+#include "ns3/mgt-headers.h" // from wifi module
+#include "ns3/wifi-mac-header.h"
+#include "ns3/wifi-information-element-vector.h"
+
+#include <vector>
+
+namespace ns3 {
+
+/**
+ * \brief Beacon is beacon header + list of arbitrary information elements
+ *
+ * It is supposed that distinct mesh protocols can use beacons to transport
+ * their own information elements.
+ */
+class MeshWifiBeacon
+{
+public:
+ /**
+ * C-tor
+ *
+ * \param ssid is SSID for beacon header
+ * \param rates is a set of supported rates
+ * \param us beacon interval in microseconds
+ */
+ MeshWifiBeacon (Ssid ssid, SupportedRates rates, uint64_t us);
+ /// Read standard Wifi beacon header
+ MgtBeaconHeader BeaconHeader () const { return m_header; }
+ /// Add information element
+ void AddInformationElement (Ptr<WifiInformationElement> ie);
+
+ /**
+ * Create wifi header for beacon frame.
+ *
+ * \param address is sender address
+ * \param mpAddress is mesh point address
+ */
+ WifiMacHeader CreateHeader (Mac48Address address, Mac48Address mpAddress);
+ /// Create frame = { beacon header + all information elements sorted by ElementId () }
+ Ptr<Packet> CreatePacket ();
+
+private:
+ /// Beacon header
+ MgtBeaconHeader m_header;
+ /// List of information elements added
+ WifiInformationElementVector m_elements;
+};
+
+}
+
+
+#endif /* MESHWIFIBEACON_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac-plugin.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIINTERFACEMACPLUGIN_H_
+#define MESHWIFIINTERFACEMACPLUGIN_H_
+
+#include "ns3/wifi-mac-header.h"
+#include "ns3/packet.h"
+#include "ns3/mac48-address.h"
+#include "ns3/mesh-wifi-beacon.h"
+#include "ns3/ref-count-base.h"
+
+namespace ns3 {
+
+class MeshWifiInterfaceMac;
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Common interface for mesh point interface MAC plugins
+ *
+ * TODO: plugins description
+ */
+class MeshWifiInterfaceMacPlugin : public RefCountBase
+{
+public:
+ /// This is for subclasses
+ virtual ~MeshWifiInterfaceMacPlugin (){};
+ /// Each plugin must be installed on interface to work
+ virtual void SetParent (Ptr<MeshWifiInterfaceMac> parent) = 0;
+ /**
+ * \brief Process received frame
+ *
+ * \return false if (and only if) frame should be dropped
+ * TODO define when MAC call this
+ */
+ virtual bool Receive (Ptr<Packet> packet, const WifiMacHeader & header) = 0;
+ /**
+ * \brief Update frame before it will be forwarded down
+ *
+ * \return false if (and only if) frame should be dropped
+ * TODO define when MAC call this, preconditions & postconditions
+ */
+ virtual bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) = 0;
+ /**
+ * \brief Update beacon before it will be formed and sent
+ *
+ * TODO define when MAC call this
+ */
+ virtual void UpdateBeacon (MeshWifiBeacon & beacon) const = 0;
+};
+
+} // namespace ns3
+#endif /* MESHWIFIINTERFACEMACPLUGIN_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,742 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/mesh-wifi-interface-mac.h"
+#include "ns3/mesh-wifi-beacon.h"
+#include "ns3/log.h"
+#include "ns3/wifi-phy.h"
+#include "ns3/dcf-manager.h"
+#include "ns3/mac-rx-middle.h"
+#include "ns3/mac-low.h"
+#include "ns3/dca-txop.h"
+#include "ns3/random-variable.h"
+#include "ns3/simulator.h"
+#include "ns3/yans-wifi-phy.h"
+#include "ns3/pointer.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/qos-tag.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshWifiInterfaceMac");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshWifiInterfaceMac);
+
+TypeId
+MeshWifiInterfaceMac::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::MeshWifiInterfaceMac")
+ .SetParent<WifiMac> ()
+ .AddConstructor<MeshWifiInterfaceMac> ()
+ .AddAttribute ( "BeaconInterval",
+ "Beacon Interval",
+ TimeValue (Seconds (0.5)),
+
+ MakeTimeAccessor (
+ &MeshWifiInterfaceMac::m_beaconInterval),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "RandomStart",
+ "Window when beacon generating starts (uniform random) in seconds",
+ TimeValue (Seconds (0.5)),
+ MakeTimeAccessor (
+ &MeshWifiInterfaceMac::m_randomStart),
+ MakeTimeChecker ()
+ )
+ .AddAttribute ( "BeaconGeneration",
+ "Enable/Disable Beaconing.",
+ BooleanValue (true),
+ MakeBooleanAccessor (
+ &MeshWifiInterfaceMac::SetBeaconGeneration, &MeshWifiInterfaceMac::GetBeaconGeneration),
+ MakeBooleanChecker ()
+ )
+ .AddTraceSource ( "TxOkHeader",
+ "The header of successfully transmitted packet",
+ MakeTraceSourceAccessor (
+ &MeshWifiInterfaceMac::m_txOkCallback)
+ )
+ .AddTraceSource ( "TxErrHeader",
+ "The header of unsuccessfully transmitted packet",
+ MakeTraceSourceAccessor (
+ &MeshWifiInterfaceMac::m_txErrCallback)
+ )
+ ;
+ return tid;
+}
+MeshWifiInterfaceMac::MeshWifiInterfaceMac ()
+{
+ NS_LOG_FUNCTION (this);
+
+ m_rxMiddle = new MacRxMiddle ();
+ m_rxMiddle->SetForwardCallback (MakeCallback (&MeshWifiInterfaceMac::Receive, this));
+
+ m_low = CreateObject<MacLow> ();
+ m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle));
+
+ m_dcfManager = new DcfManager ();
+ m_dcfManager->SetupLowListener (m_low);
+
+ m_beaconDca = CreateObject<DcaTxop> ();
+ m_beaconDca->SetLow (m_low);
+ m_beaconDca->SetMinCw (0);
+ m_beaconDca->SetMaxCw (0);
+ m_beaconDca->SetAifsn (1);
+ m_beaconDca->SetManager (m_dcfManager);
+
+ SetQueue (AC_VO);
+ SetQueue (AC_VI);
+ SetQueue (AC_BE);
+ SetQueue (AC_BK);
+}
+MeshWifiInterfaceMac::~MeshWifiInterfaceMac ()
+{
+ NS_LOG_FUNCTION (this);
+}
+//-----------------------------------------------------------------------------
+// WifiMac inherited
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::SetSlot (Time slotTime)
+{
+ NS_LOG_FUNCTION (this << slotTime);
+ m_dcfManager->SetSlot (slotTime);
+ m_low->SetSlotTime (slotTime);
+ m_slot = slotTime;
+}
+void
+MeshWifiInterfaceMac::SetSifs (Time sifs)
+{
+ NS_LOG_FUNCTION (this << sifs);
+ m_dcfManager->SetSifs (sifs);
+ m_low->SetSifs (sifs);
+ m_sifs = sifs;
+}
+void
+MeshWifiInterfaceMac::SetAckTimeout (Time ackTimeout)
+{
+ m_low->SetAckTimeout (ackTimeout);
+}
+void
+MeshWifiInterfaceMac::SetCtsTimeout (Time ctsTimeout)
+{
+ m_low->SetCtsTimeout (ctsTimeout);
+}
+void
+MeshWifiInterfaceMac::SetPifs (Time pifs)
+{
+ NS_LOG_FUNCTION (this << pifs);
+ m_pifs = pifs;
+}
+void
+MeshWifiInterfaceMac::SetEifsNoDifs (Time eifsNoDifs)
+{
+ NS_LOG_FUNCTION (this << eifsNoDifs);
+ m_dcfManager->SetEifsNoDifs (eifsNoDifs);
+ m_eifsNoDifs = eifsNoDifs;
+}
+Time
+MeshWifiInterfaceMac::GetSlot () const
+{
+ return m_slot;
+}
+Time
+MeshWifiInterfaceMac::GetSifs () const
+{
+ return m_sifs;
+}
+Time
+MeshWifiInterfaceMac::GetEifsNoDifs () const
+{
+ return m_eifsNoDifs;
+}
+Time
+MeshWifiInterfaceMac::GetAckTimeout () const
+{
+ return m_low->GetAckTimeout ();
+}
+Time
+MeshWifiInterfaceMac::GetCtsTimeout () const
+{
+ return m_low->GetCtsTimeout ();
+}
+Time
+MeshWifiInterfaceMac::GetPifs () const
+{
+ return m_low->GetPifs ();
+}
+void
+MeshWifiInterfaceMac::SetWifiPhy (Ptr<WifiPhy> phy)
+{
+ NS_LOG_FUNCTION (this << phy);
+ m_phy = phy;
+ m_dcfManager->SetupPhyListener (phy);
+ m_low->SetPhy (phy);
+}
+void
+MeshWifiInterfaceMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager)
+{
+ NS_LOG_FUNCTION (this << stationManager);
+ m_stationManager = stationManager;
+ for (Queues::const_iterator i = m_queues.begin (); i != m_queues.end (); i++)
+ {
+ i->second->SetWifiRemoteStationManager (stationManager);
+ }
+ m_beaconDca->SetWifiRemoteStationManager (stationManager);
+ m_low->SetWifiRemoteStationManager (stationManager);
+}
+void
+MeshWifiInterfaceMac::Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from)
+{
+ NS_LOG_FUNCTION (this << packet << to << from);
+ ForwardDown (packet, from, to);
+}
+void
+MeshWifiInterfaceMac::Enqueue (Ptr<const Packet> packet, Mac48Address to)
+{
+ NS_LOG_FUNCTION (this << packet << to);
+ ForwardDown (packet, m_low->GetAddress (), to);
+}
+bool
+MeshWifiInterfaceMac::SupportsSendFrom () const
+{
+ return true;
+}
+void
+MeshWifiInterfaceMac::SetForwardUpCallback (
+ Callback<void, Ptr<Packet> , Mac48Address, Mac48Address> upCallback)
+{
+ NS_LOG_FUNCTION (this);
+ m_upCallback = upCallback;
+}
+void
+MeshWifiInterfaceMac::SetLinkUpCallback (Callback<void> linkUp)
+{
+ NS_LOG_FUNCTION (this);
+ if (!linkUp.IsNull ())
+ {
+ linkUp ();
+ }
+}
+void
+MeshWifiInterfaceMac::SetLinkDownCallback (Callback<void> linkDown)
+{
+ NS_LOG_FUNCTION (this);
+}
+Mac48Address
+MeshWifiInterfaceMac::GetAddress () const
+{
+ return m_address;
+}
+Mac48Address
+MeshWifiInterfaceMac::GetBssid () const
+{
+ return m_address;
+}
+Ssid
+MeshWifiInterfaceMac::GetSsid () const
+{
+ return m_meshId;
+}
+void
+MeshWifiInterfaceMac::SetAddress (Mac48Address address)
+{
+ NS_LOG_FUNCTION (address);
+ m_low->SetAddress (address);
+ m_address = address;
+}
+void
+MeshWifiInterfaceMac::SetSsid (Ssid ssid)
+{
+ NS_LOG_FUNCTION (ssid);
+ m_meshId = ssid;
+}
+void
+MeshWifiInterfaceMac::DoDispose ()
+{
+ NS_LOG_FUNCTION (this);
+ delete m_rxMiddle;
+ delete m_dcfManager;
+ //Delete smart pointers:
+ m_rxMiddle = 0;
+ m_low = 0;
+ m_dcfManager = 0;
+ m_phy = 0;
+ m_queues.clear ();
+ m_beaconSendEvent.Cancel ();
+ m_beaconDca = 0;
+
+ WifiMac::DoDispose ();
+}
+//-----------------------------------------------------------------------------
+// Plugins
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::InstallPlugin (Ptr<MeshWifiInterfaceMacPlugin> plugin)
+{
+ NS_LOG_FUNCTION (this);
+
+ plugin->SetParent (this);
+ m_plugins.push_back (plugin);
+}
+//-----------------------------------------------------------------------------
+// Switch channels
+//-----------------------------------------------------------------------------
+uint16_t
+MeshWifiInterfaceMac::GetFrequencyChannel () const
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_phy != 0); // need PHY to set/get channel
+
+ Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+ if (phy != 0)
+ {
+ return phy->GetChannelNumber ();
+ }
+ else
+ {
+ return 0;
+ }
+}
+void
+MeshWifiInterfaceMac::SwitchFrequencyChannel (uint16_t new_id)
+{
+ NS_LOG_FUNCTION (this);
+ NS_ASSERT (m_phy != 0); // need PHY to set/get channel
+ /* TODO
+ *
+ * Correct channel switching is:
+ *
+ * 1. Interface down, e.g. to stop packets from layer 3
+ * 2. Wait before all output queues will be empty
+ * 3. Switch PHY channel
+ * 4. Interface up
+ *
+ * Now we use dirty channel switch -- just change frequency
+ */
+ Ptr<YansWifiPhy> phy = m_phy->GetObject<YansWifiPhy> ();
+ phy->SetChannelNumber (new_id);
+ // Don't know NAV on new channel
+ m_dcfManager->NotifyNavResetNow (Seconds (0));
+}
+//-----------------------------------------------------------------------------
+// Forward frame up/down
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst)
+{
+ NS_LOG_FUNCTION (this << packet << src);
+ m_upCallback (packet, src, dst);
+}
+
+void
+MeshWifiInterfaceMac::ForwardDown (Ptr<const Packet> const_packet, Mac48Address from, Mac48Address to)
+{
+ // copy packet to allow modifications
+ Ptr<Packet> packet = const_packet->Copy ();
+ WifiMacHeader hdr;
+ hdr.SetTypeData ();
+ hdr.SetAddr2 (GetAddress ());
+ hdr.SetAddr3 (to);
+ hdr.SetAddr4 (from);
+ hdr.SetDsFrom ();
+ hdr.SetDsTo ();
+ // Fill QoS fields:
+ hdr.SetQosAckPolicy (WifiMacHeader::NORMAL_ACK);
+ hdr.SetQosNoEosp ();
+ hdr.SetQosNoAmsdu ();
+ hdr.SetQosTxopLimit (0);
+ // Address 1 is unknwon here. Routing plugin is responsible to correctly set it.
+ hdr.SetAddr1 (Mac48Address ());
+ // Filter packet through all installed plugins
+ for (PluginList::const_iterator i = m_plugins.end () - 1; i != m_plugins.begin () - 1; i--)
+ {
+ bool drop = !((*i)->UpdateOutcomingFrame (packet, hdr, from, to));
+ if (drop)
+ {
+ return; // plugin drops frame
+ }
+ }
+ // Assert that address1 is set. Assert will fail e.g. if there is no installed routing plugin.
+ NS_ASSERT (hdr.GetAddr1 () != Mac48Address ());
+ // Queue frame
+ WifiRemoteStation *destination = m_stationManager->Lookup (to);
+ if (destination->IsBrandNew ())
+ {
+ // in adhoc mode, we assume that every destination
+ // supports all the rates we support.
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ destination->AddSupportedMode (m_phy->GetMode (i));
+ }
+ destination->RecordDisassociated ();
+ }
+ //Classify: application sets a tag, which is removed here
+ // Get Qos tag:
+ AccessClass ac = AC_BE;
+ QosTag tag;
+ if (packet->RemovePacketTag (tag))
+ {
+ ac = QosUtilsMapTidToAc (tag.Get ());
+ }
+ m_stats.sentFrames++;
+ m_stats.sentBytes += packet->GetSize ();
+ NS_ASSERT (m_queues.find (ac) != m_queues.end ());
+ m_queues[ac]->Queue (packet, hdr);
+}
+void
+MeshWifiInterfaceMac::SendManagementFrame (Ptr<Packet> packet, const WifiMacHeader& hdr)
+{
+ //Filter management frames:
+ WifiMacHeader header = hdr;
+ for (PluginList::const_iterator i = m_plugins.end () - 1; i != m_plugins.begin () - 1; i--)
+ {
+ bool drop = !((*i)->UpdateOutcomingFrame (packet, header, Mac48Address (), Mac48Address ()));
+ if (drop)
+ {
+ return; // plugin drops frame
+ }
+ }
+ m_stats.sentFrames++;
+ m_stats.sentBytes += packet->GetSize ();
+ if ((m_queues.find (AC_VO) == m_queues.end ()) || (m_queues.find (AC_BK) == m_queues.end ()))
+ {
+ NS_FATAL_ERROR ("Voice or Background queue is not set up!");
+ }
+ /*
+ * When we send a management frame - it is better to enqueue it to
+ * priority queue. But when we send a broadcast management frame,
+ * like PREQ, little MinCw value may cause collisions during
+ * retransmissions (two neighbor stations may choose the same window
+ * size, and two packets will be collided). So, broadcast management
+ * frames go to BK queue.
+ */
+ if (hdr.GetAddr1 () != Mac48Address::GetBroadcast ())
+ {
+ m_queues[AC_VO]->Queue (packet, header);
+ }
+ else
+ {
+ m_queues[AC_BK]->Queue (packet, header);
+ }
+}
+SupportedRates
+MeshWifiInterfaceMac::GetSupportedRates () const
+{
+ // set the set of supported rates and make sure that we indicate
+ // the Basic Rate set in this set of supported rates.
+ SupportedRates rates;
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ WifiMode mode = m_phy->GetMode (i);
+ rates.AddSupportedRate (mode.GetDataRate ());
+ }
+ // set the basic rates
+ for (uint32_t j = 0; j < m_stationManager->GetNBasicModes (); j++)
+ {
+ WifiMode mode = m_stationManager->GetBasicMode (j);
+ rates.SetBasicRate (mode.GetDataRate ());
+ }
+ return rates;
+}
+bool
+MeshWifiInterfaceMac::CheckSupportedRates (SupportedRates rates) const
+{
+ for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
+ {
+ WifiMode mode = m_stationManager->GetBasicMode (i);
+ if (!rates.IsSupportedRate (mode.GetDataRate ()))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+//-----------------------------------------------------------------------------
+// Beacons
+//-----------------------------------------------------------------------------
+void
+MeshWifiInterfaceMac::SetRandomStartDelay (Time interval)
+{
+ NS_LOG_FUNCTION (this << interval);
+ m_randomStart = interval;
+}
+void
+MeshWifiInterfaceMac::SetBeaconInterval (Time interval)
+{
+ NS_LOG_FUNCTION (this << interval);
+ m_beaconInterval = interval;
+}
+Time
+MeshWifiInterfaceMac::GetBeaconInterval () const
+{
+ return m_beaconInterval;
+}
+void
+MeshWifiInterfaceMac::SetBeaconGeneration (bool enable)
+{
+ NS_LOG_FUNCTION (this << enable);
+ if (enable)
+ {
+ // Now start sending beacons after some random delay (to avoid collisions)
+ UniformVariable coefficient (0.0, m_randomStart.GetSeconds ());
+ Time randomStart = Seconds (coefficient.GetValue ());
+
+ m_beaconSendEvent = Simulator::Schedule (randomStart, &MeshWifiInterfaceMac::SendBeacon, this);
+ m_tbtt = Simulator::Now () + randomStart;
+ }
+ else
+ {
+ // stop sending beacons
+ m_beaconSendEvent.Cancel ();
+ }
+}
+bool
+MeshWifiInterfaceMac::GetBeaconGeneration () const
+{
+ return m_beaconSendEvent.IsRunning ();
+}
+Time
+MeshWifiInterfaceMac::GetTbtt () const
+{
+ return m_tbtt;
+}
+void
+MeshWifiInterfaceMac::ShiftTbtt (Time shift)
+{
+ // User of ShiftTbtt () must take care don't shift it to the past
+ NS_ASSERT (GetTbtt () + shift > Simulator::Now ());
+
+ m_tbtt += shift;
+ // Shift scheduled event
+ Simulator::Cancel (m_beaconSendEvent);
+ m_beaconSendEvent = Simulator::Schedule (GetTbtt () - Simulator::Now (), &MeshWifiInterfaceMac::SendBeacon,
+ this);
+}
+void
+MeshWifiInterfaceMac::ScheduleNextBeacon ()
+{
+ m_tbtt += GetBeaconInterval ();
+ m_beaconSendEvent = Simulator::Schedule (GetBeaconInterval (), &MeshWifiInterfaceMac::SendBeacon, this);
+}
+void
+MeshWifiInterfaceMac::SendBeacon ()
+{
+ NS_LOG_FUNCTION (this);
+ NS_LOG_DEBUG (GetAddress () << " is sending beacon");
+
+ NS_ASSERT (!m_beaconSendEvent.IsRunning ());
+ NS_ASSERT (Simulator::Now ().GetMicroSeconds () == GetTbtt ().GetMicroSeconds ()); // assert that beacon is just on time
+
+ // Form & send beacon
+ MeshWifiBeacon beacon (GetSsid (), GetSupportedRates (), m_beaconInterval.GetMicroSeconds ());
+
+ // Ask all plugins to add their specific information elements to beacon
+ for (PluginList::const_iterator i = m_plugins.begin (); i != m_plugins.end (); ++i)
+ {
+ (*i)->UpdateBeacon (beacon);
+ }
+ m_beaconDca->Queue (beacon.CreatePacket (), beacon.CreateHeader (GetAddress (), GetMeshPointAddress ()));
+
+ ScheduleNextBeacon ();
+}
+void
+MeshWifiInterfaceMac::Receive (Ptr<Packet> packet, WifiMacHeader const *hdr)
+{
+ // Process beacon
+ if ((hdr->GetAddr1 () != GetAddress ()) && (hdr->GetAddr1 () != Mac48Address::GetBroadcast ()))
+ {
+ return;
+ }
+ if (hdr->IsBeacon ())
+ {
+ m_stats.recvBeacons++;
+ MgtBeaconHeader beacon_hdr;
+ Mac48Address from = hdr->GetAddr2 ();
+
+ packet->PeekHeader (beacon_hdr);
+
+ NS_LOG_DEBUG ("Beacon received from " << hdr->GetAddr2 () << " I am " << GetAddress () << " at "
+ << Simulator::Now ().GetMicroSeconds () << " microseconds");
+
+ // update supported rates
+ if (beacon_hdr.GetSsid ().IsEqual (GetSsid ()))
+ {
+ SupportedRates rates = beacon_hdr.GetSupportedRates ();
+ WifiRemoteStation * peerSta = m_stationManager->Lookup (hdr->GetAddr2 ());
+
+ for (uint32_t i = 0; i < m_phy->GetNModes (); i++)
+ {
+ WifiMode mode = m_phy->GetMode (i);
+ if (rates.IsSupportedRate (mode.GetDataRate ()))
+ {
+ peerSta->AddSupportedMode (mode);
+ if (rates.IsBasicRate (mode.GetDataRate ()))
+ {
+ m_stationManager->AddBasicMode (mode);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_stats.recvBytes += packet->GetSize ();
+ m_stats.recvFrames++;
+ }
+ // Filter frame through all installed plugins
+ for (PluginList::iterator i = m_plugins.begin (); i != m_plugins.end (); ++i)
+ {
+ bool drop = !((*i)->Receive (packet, *hdr));
+ if (drop)
+ {
+ return; // plugin drops frame
+ }
+ }
+ // Check if QoS tag exists and add it:
+ if (hdr->IsQosData ())
+ {
+ packet->AddPacketTag (QosTag (hdr->GetQosTid ()));
+ }
+ // Forward data up
+ if (hdr->IsData ())
+ {
+ ForwardUp (packet, hdr->GetAddr4 (), hdr->GetAddr3 ());
+ }
+}
+uint32_t
+MeshWifiInterfaceMac::GetLinkMetric (Mac48Address peerAddress)
+{
+ uint32_t metric = 1;
+ if (!m_linkMetricCallback.IsNull ())
+ {
+ metric = m_linkMetricCallback (peerAddress, this);
+ }
+ return metric;
+}
+void
+MeshWifiInterfaceMac::SetLinkMetricCallback (Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > cb)
+{
+ m_linkMetricCallback = cb;
+}
+Ptr<WifiRemoteStationManager>
+MeshWifiInterfaceMac::GetStationManager ()
+{
+ return m_stationManager;
+}
+void
+MeshWifiInterfaceMac::SetMeshPointAddress (Mac48Address a)
+{
+ m_mpAddress = a;
+}
+Mac48Address
+MeshWifiInterfaceMac::GetMeshPointAddress () const
+{
+ return m_mpAddress;
+}
+//Statistics:
+MeshWifiInterfaceMac::Statistics::Statistics () :
+ recvBeacons (0), sentFrames (0), sentBytes (0), recvFrames (0), recvBytes (0)
+{
+}
+void
+MeshWifiInterfaceMac::Statistics::Print (std::ostream & os) const
+{
+ os << "<Statistics "
+ // TODO txBeacons
+ "rxBeacons=\"" << recvBeacons << "\" "
+ "txFrames=\"" << sentFrames << "\" "
+ "txBytes=\"" << sentBytes << "\" "
+ "rxFrames=\"" << recvFrames << "\" "
+ "rxBytes=\"" << recvBytes << "\"/>" << std::endl;
+}
+void
+MeshWifiInterfaceMac::Report (std::ostream & os) const
+{
+ os << "<Interface "
+ "BeaconInterval=\"" << GetBeaconInterval ().GetSeconds () << "\" "
+ "Channel=\"" << GetFrequencyChannel () << "\" "
+ "Address = \"" << GetAddress () << "\">" << std::endl;
+ m_stats.Print (os);
+ os << "</Interface>" << std::endl;
+}
+void
+MeshWifiInterfaceMac::ResetStats ()
+{
+ m_stats = Statistics::Statistics ();
+}
+void
+MeshWifiInterfaceMac::SetQueue (AccessClass ac)
+{
+ if (m_queues.find (ac) != m_queues.end ())
+ {
+ NS_LOG_WARN ("Queue is already set!");
+ return;
+ }
+ Ptr<DcaTxop> queue = Create<DcaTxop> ();
+ queue->SetLow (m_low);
+ queue->SetManager (m_dcfManager);
+ queue->SetTxOkCallback (MakeCallback (&MeshWifiInterfaceMac::TxOk, this));
+ queue->SetTxFailedCallback (MakeCallback (&MeshWifiInterfaceMac::TxFailed, this));
+
+ m_queues.insert (std::make_pair (ac, queue));
+}
+void
+MeshWifiInterfaceMac::TxOk (WifiMacHeader const &hdr)
+{
+ m_txOkCallback (hdr);
+}
+void
+MeshWifiInterfaceMac::TxFailed (WifiMacHeader const &hdr)
+{
+ m_txErrCallback (hdr);
+}
+
+void
+MeshWifiInterfaceMac::FinishConfigureStandard (enum WifiPhyStandard standard)
+{
+ switch (standard)
+ {
+ case WIFI_PHY_STANDARD_holland:
+ // fall through
+ case WIFI_PHY_STANDARD_80211a:
+ // fall through
+ case WIFI_PHY_STANDARD_80211_10Mhz:
+ // fall through
+ case WIFI_PHY_STANDARD_80211_5Mhz:
+ ConfigureDcf (m_queues[AC_BK], 15, 1023, AC_BK);
+ ConfigureDcf (m_queues[AC_BE], 15, 1023, AC_BE);
+ ConfigureDcf (m_queues[AC_VI], 15, 1023, AC_VI);
+ ConfigureDcf (m_queues[AC_VO], 15, 1023, AC_VO);
+ break;
+ case WIFI_PHY_STANDARD_80211b:
+ ConfigureDcf (m_queues[AC_BK], 31, 1023, AC_BK);
+ ConfigureDcf (m_queues[AC_BE], 31, 1023, AC_BE);
+ ConfigureDcf (m_queues[AC_VI], 31, 1023, AC_VI);
+ ConfigureDcf (m_queues[AC_VO], 31, 1023, AC_VO);
+ break;
+ default:
+ NS_ASSERT (false);
+ break;
+ }
+}
+
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh-wifi-interface-mac.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,255 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef MESHWIFIINTERFACEMAC_H_
+#define MESHWIFIINTERFACEMAC_H_
+
+#include <stdint.h>
+#include <map>
+#include "ns3/mac48-address.h"
+#include "ns3/mgt-headers.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/wifi-mac.h"
+#include "ns3/mesh-wifi-interface-mac-plugin.h"
+#include "ns3/event-id.h"
+#include "qos-utils.h"
+namespace ns3 {
+
+class WifiMacHeader;
+class DcaTxop;
+class WifiPhy;
+class DcfManager;
+class MacRxMiddle;
+class MacLow;
+/**
+ * \ingroup mesh
+ *
+ * \brief Basic MAC of mesh point Wi-Fi interface. Its function is extendable through plugins mechanism.
+ *
+ * Now only three output queues are used:
+ * - beacons (PIFS and no backoff),
+ * - background traffic,
+ * - management and priority traffic.
+ *
+ */
+class MeshWifiInterfaceMac : public WifiMac
+{
+public:
+ /// Never forget to support typeid
+ static TypeId GetTypeId ();
+ /// C-tor
+ MeshWifiInterfaceMac ();
+ /// D-tor
+ virtual ~MeshWifiInterfaceMac ();
+
+ ///\name Inherited from WifiMac
+ //\{
+ virtual void SetSlot (Time slotTime);
+ virtual void SetSifs (Time sifs);
+ virtual void SetPifs (Time pifs);
+ virtual void SetCtsTimeout (Time ctsTimeout);
+ virtual void SetAckTimeout (Time ackTimeout);
+ virtual void SetEifsNoDifs (Time eifsNoDifs);
+ virtual Time GetSlot () const;
+ virtual Time GetSifs () const;
+ virtual Time GetPifs () const;
+ virtual Time GetCtsTimeout () const;
+ virtual Time GetAckTimeout () const;
+ virtual Time GetEifsNoDifs () const;
+ virtual void SetWifiPhy (Ptr<WifiPhy> phy);
+ virtual void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager);
+ virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from);
+ virtual void Enqueue (Ptr<const Packet> packet, Mac48Address to);
+ virtual bool SupportsSendFrom () const;
+ virtual void SetForwardUpCallback (Callback<void,Ptr<Packet>, Mac48Address, Mac48Address> upCallback);
+ virtual void SetLinkUpCallback (Callback<void> linkUp);
+ virtual void SetLinkDownCallback (Callback<void> linkDown);
+ virtual Mac48Address GetAddress () const;
+ virtual Mac48Address GetBssid () const;
+ virtual Ssid GetSsid () const;
+ virtual void SetAddress (Mac48Address address);
+ virtual void SetSsid (Ssid ssid);
+ //\}
+
+ ///\name Each mesh point interfaces must know the mesh point address
+ //\{
+ void SetMeshPointAddress (Mac48Address);
+ Mac48Address GetMeshPointAddress () const;
+ //\}
+ ///\name Beacons
+ //\{
+ /// Set maximum initial random delay before first beacon
+ void SetRandomStartDelay (Time interval);
+ /// Set interval between two successive beacons
+ void SetBeaconInterval (Time interval);
+ /// \return interval between two beacons
+ Time GetBeaconInterval () const;
+ /**
+ * \brief Next beacon frame time
+ *
+ * This is supposed to be used by any entity managing beacon collision avoidance (e.g. Peer management protocol in 802.11s)
+ */
+ Time GetTbtt () const;
+ /**
+ * \brief Shift TBTT.
+ *
+ * This is supposed to be used by any entity managing beacon collision avoidance (e.g. Peer management protocol in 802.11s)
+ *
+ * \attention User of ShiftTbtt () must take care to not shift it to the past.
+ */
+ void ShiftTbtt (Time shift);
+ //\}
+
+ ///\name Plugins
+ //\{
+ /// Install plugin. TODO return unique ID to allow unregister plugins
+ void InstallPlugin (Ptr<MeshWifiInterfaceMacPlugin> plugin);
+ //\}
+
+ /** \name Channel switching
+ *
+ * Channel center frequency = Channel starting frequency + 5 * channel_id (MHz),
+ * where Starting channel frequency is standard-dependent as defined in IEEE 802.11-2007 17.3.8.3.2.
+ *
+ * Number of channels to use must be limited elsewhere.
+ */
+ //\{
+ /// Current channel Id
+ uint16_t GetFrequencyChannel () const;
+ /// Switch channel
+ void SwitchFrequencyChannel (uint16_t new_id);
+ //\}
+
+ /// To be used by plugins sending management frames.
+ void SendManagementFrame (Ptr<Packet> frame, const WifiMacHeader& hdr);
+ /// \return true if rates are supported
+ bool CheckSupportedRates (SupportedRates rates) const;
+ /// \return list of supported bitrates
+ SupportedRates GetSupportedRates () const;
+ ///\ name Metric Calculation routines:
+ ///\{
+ void SetLinkMetricCallback (Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > cb);
+ uint32_t GetLinkMetric (Mac48Address peerAddress);
+ Ptr<WifiRemoteStationManager> GetStationManager ();
+ ///\}
+ ///\brief Statistics:
+ void Report (std::ostream &) const;
+ void ResetStats ();
+ /// Enable/disable beacons
+ void SetBeaconGeneration (bool enable);
+ void SetQueue (AccessClass ac);
+ virtual void FinishConfigureStandard (enum WifiPhyStandard standard);
+private:
+ /// Frame receive handler
+ void Receive (Ptr<Packet> packet, WifiMacHeader const *hdr);
+ /// Forward frame to mesh point
+ virtual void ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst);
+ /// Send frame. Frame is supposed to be tagged by routing information. TODO: clarify this point
+ void ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to);
+ // Notify about tx OK/Error frames:
+ void TxOk (WifiMacHeader const &hdr);
+ void TxFailed (WifiMacHeader const &hdr);
+ /// Send beacon
+ void SendBeacon ();
+ /// Schedule next beacon
+ void ScheduleNextBeacon ();
+ /// Get current beaconing status
+ bool GetBeaconGeneration () const;
+ /// Real d-tor
+ virtual void DoDispose ();
+
+private:
+ ///\name Wifi MAC internals
+ //\{
+ typedef std::map<AccessClass, Ptr<DcaTxop> > Queues;
+ Queues m_queues;
+ Ptr<DcaTxop> m_beaconDca;
+ Ptr<WifiRemoteStationManager> m_stationManager;
+ Ptr<WifiPhy> m_phy;
+ Callback<void, Ptr<Packet> , Mac48Address, Mac48Address> m_upCallback;
+ //\}
+
+ ///\name Wifi timing intervals
+ //\{
+ Time m_slot;
+ Time m_sifs;
+ Time m_pifs;
+ Time m_ackTimeout;
+ Time m_ctsTimeout;
+ Time m_eifsNoDifs;
+ //\}
+
+ ///\name Mesh timing intervals
+ //\{
+ /// Beaconing interval.
+ Time m_beaconInterval;
+ /// Maximum delay before first beacon
+ Time m_randomStart;
+ /// Time for the next frame
+ Time m_tbtt;
+ //\}
+
+ /// DCF implementation
+ DcfManager* m_dcfManager;
+ /// Middle MAC sublayer
+ MacRxMiddle* m_rxMiddle;
+ /// Low MAC sublayer
+ Ptr<MacLow> m_low;
+ /// My address
+ Mac48Address m_address;
+ /// Mesh point address
+ Mac48Address m_mpAddress;
+ /// SSID
+ Ssid m_meshId;
+
+ /// "Timer" for the next beacon
+ EventId m_beaconSendEvent;
+
+ typedef std::vector<Ptr<MeshWifiInterfaceMacPlugin> > PluginList;
+ /// List of all installed plugins
+ PluginList m_plugins;
+ Callback<uint32_t, Mac48Address, Ptr<MeshWifiInterfaceMac> > m_linkMetricCallback;
+ ///\name Statistics:
+ ///\{
+ struct Statistics
+ {
+ uint16_t recvBeacons;
+ uint32_t sentFrames;
+ uint32_t sentBytes;
+ uint32_t recvFrames;
+ uint32_t recvBytes;
+ void
+ Print (std::ostream & os) const;
+ Statistics ();
+ };
+ Statistics m_stats;
+ ///\}
+ TracedCallback<WifiMacHeader const &> m_txOkCallback;
+ TracedCallback<WifiMacHeader const &> m_txErrCallback;
+
+};
+
+} // namespace ns3
+
+#endif /* MESHWIFIINTERFACEMAC_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/mesh.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,30 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ *
+ * This is toplevel mesh module description
+ */
+
+/**
+ * \ingroup devices
+ * \defgroup mesh Mesh
+ *
+ * \brief Layer 2 mobile ad hoc wireless (aka mesh) networking
+ *
+ * see http://www.nsnam.org/wiki/index.php/Mesh for module architectural description.
+ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/waf Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../waf "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/wifi-information-element-vector.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,482 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "wifi-information-element-vector.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+#include <algorithm>
+// All information elements:
+#include "dot11s/ie-dot11s-beacon-timing.h"
+#include "dot11s/ie-dot11s-configuration.h"
+#include "dot11s/ie-dot11s-id.h"
+#include "dot11s/ie-dot11s-metric-report.h"
+#include "dot11s/ie-dot11s-peer-management.h"
+#include "dot11s/ie-dot11s-peering-protocol.h"
+#include "dot11s/ie-dot11s-perr.h"
+#include "dot11s/ie-dot11s-prep.h"
+#include "dot11s/ie-dot11s-preq.h"
+#include "dot11s/ie-dot11s-rann.h"
+
+namespace ns3 {
+bool
+operator< (WifiInformationElement const & a, WifiInformationElement const & b)
+{
+ return (a.ElementId () < b.ElementId ());
+}
+
+WifiInformationElementVector::WifiInformationElementVector () :
+ m_maxSize (1500)
+{
+}
+WifiInformationElementVector::~WifiInformationElementVector ()
+{
+}
+TypeId
+WifiInformationElementVector::GetTypeId ()
+{
+ static TypeId tid = TypeId ("ns3::WifiInformationElementVector")
+ .SetParent<Header> ();
+ return tid;
+}
+TypeId
+WifiInformationElementVector::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+uint32_t
+WifiInformationElementVector::GetSerializedSize () const
+{
+ return GetSize ();
+}
+void
+WifiInformationElementVector::Serialize (Buffer::Iterator start) const
+{
+ for(std::vector<Ptr<WifiInformationElement> >::const_iterator i = m_elements.begin (); i != m_elements.end (); i ++)
+ {
+ start.WriteU8((*i)->ElementId ());
+ start.WriteU8 ((*i)->GetInformationSize ());
+ (*i)->SerializeInformation (start);
+ start.Next ((*i)->GetInformationSize ());
+ }
+}
+uint32_t
+WifiInformationElementVector::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ uint32_t size = start.GetSize();
+ while (size > 0)
+ {
+ uint32_t deserialized = DeserializeSingleIe(i);
+ i.Next (deserialized);
+ size -= deserialized;
+ }
+ return i.GetDistanceFrom(start);
+}
+uint32_t
+WifiInformationElementVector::DeserializeSingleIe(Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+ uint8_t id = i.ReadU8 ();
+ uint8_t length = i.ReadU8 ();
+ Ptr<WifiInformationElement> newElement;
+ switch (id)
+ {
+ case IE11S_MESH_CONFIGURATION:
+ newElement = Create<dot11s::IeConfiguration> ();
+ break;
+ case IE11S_MESH_ID:
+ newElement = Create<dot11s::IeMeshId> ();
+ break;
+ case IE11S_LINK_METRIC_REPORT:
+ newElement = Create<dot11s::IeLinkMetricReport> ();
+ break;
+ case IE11S_PEERING_MANAGEMENT:
+ newElement = Create<dot11s::IePeerManagement> ();
+ break;
+ case IE11S_BEACON_TIMING:
+ newElement = Create<dot11s::IeBeaconTiming> ();
+ break;
+ case IE11S_RANN:
+ newElement = Create<dot11s::IeRann> ();
+ break;
+ case IE11S_PREQ:
+ newElement = Create<dot11s::IePreq> ();
+ break;
+ case IE11S_PREP:
+ newElement = Create<dot11s::IePrep> ();
+ break;
+ case IE11S_PERR:
+ newElement = Create<dot11s::IePerr> ();
+ break;
+ case IE11S_MESH_PEERING_PROTOCOL_VERSION:
+ newElement = Create<dot11s::IePeeringProtocol> ();
+ break;
+ default:
+ NS_FATAL_ERROR ("Information element " << (uint16_t) id << " is not implemented");
+ return 0;
+ }
+ if (GetSize () + length > m_maxSize)
+ {
+ NS_FATAL_ERROR ("Check max size for information element!");
+ }
+ newElement->DeserializeInformation (i, length);
+ i.Next (length);
+ m_elements.push_back (newElement);
+ return i.GetDistanceFrom(start);
+}
+void
+WifiInformationElementVector::Print(std::ostream & os) const
+{
+ //TODO
+}
+void
+WifiInformationElementVector::SetMaxSize (uint16_t size)
+{
+ m_maxSize = size;
+}
+WifiInformationElementVector::Iterator
+WifiInformationElementVector::Begin ()
+{
+ return m_elements.begin ();
+}
+WifiInformationElementVector::Iterator
+WifiInformationElementVector::End ()
+{
+ return m_elements.end ();
+}
+bool
+WifiInformationElementVector::AddInformationElement (Ptr<WifiInformationElement> element)
+{
+ if (element->GetInformationSize () + 2 + GetSize () > m_maxSize)
+ {
+ return false;
+ }
+ m_elements.push_back (element);
+ return true;
+}
+Ptr<WifiInformationElement>
+WifiInformationElementVector::FindFirst (enum WifiElementId id) const
+{
+ for (IE_VECTOR::const_iterator i = m_elements.begin (); i != m_elements.end (); i++)
+ {
+ if ((*i)->ElementId () == id)
+ {
+ return (*i);
+ }
+ }
+ return 0;
+}
+namespace {
+struct PIEComparator
+{
+ bool
+ operator () (Ptr<WifiInformationElement> a, Ptr<WifiInformationElement> b) const
+ {
+ return ((*PeekPointer (a)) < (*PeekPointer (b)));
+ }
+};
+}
+uint32_t
+WifiInformationElementVector::GetSize () const
+{
+ uint32_t size = 0;
+ for (IE_VECTOR::const_iterator i = m_elements.begin (); i != m_elements.end (); i++)
+ {
+ size += ((*i)->GetInformationSize () + 2);
+ }
+ return size;
+}
+bool
+operator== (const WifiInformationElementVector & a, const WifiInformationElementVector & b)
+{
+ if (a.m_elements.size () != b.m_elements.size ())
+ {
+ NS_ASSERT(false);
+ return false;
+ }
+ WifiInformationElementVector::IE_VECTOR::const_iterator j = b.m_elements.begin ();
+ for (WifiInformationElementVector::IE_VECTOR::const_iterator i = a.m_elements.begin (); i
+ != a.m_elements.end (); i++, j++)
+ {
+ if ((*i)->ElementId () != (*j)->ElementId ())
+ {
+ return false;
+ }
+ if ((*i)->GetInformationSize () != (*j)->GetInformationSize ())
+ {
+ return false;
+ }
+ uint8_t id = (*i)->ElementId ();
+ switch (id)
+ {
+ case IE11S_MESH_CONFIGURATION:
+ if (DynamicCast<dot11s::IeConfiguration> ((*i)) == 0)
+ {
+ return false;
+ }
+ if (DynamicCast<dot11s::IeConfiguration> ((*j)) == 0)
+ {
+ return false;
+ }
+ if (!(*DynamicCast<dot11s::IeConfiguration> ((*i)) == *DynamicCast<dot11s::IeConfiguration> ((*j))))
+ {
+ return false;
+ }
+ break;
+ case IE11S_MESH_ID:
+ if (DynamicCast<dot11s::IeMeshId> ((*i)) == 0)
+ {
+ return false;
+ }
+ if (DynamicCast<dot11s::IeMeshId> ((*j)) == 0)
+ {
+ return false;
+ }
+ if (!(*DynamicCast<dot11s::IeMeshId> ((*i)) == *DynamicCast<dot11s::IeMeshId> ((*j))))
+ {
+ return false;
+ }
+ break;
+ case IE11S_LINK_METRIC_REPORT:
+ if (DynamicCast<dot11s::IeLinkMetricReport> ((*i)) == 0)
+ {
+ return false;
+ }
+ if (DynamicCast<dot11s::IeLinkMetricReport> ((*j)) == 0)
+ {
+ return false;
+ }
+ if (!(*DynamicCast<dot11s::IeLinkMetricReport> ((*i)) == *DynamicCast<dot11s::IeLinkMetricReport> (
+ (*j))))
+ {
+ return false;
+ }
+ break;
+ case IE11S_PEERING_MANAGEMENT:
+ if (DynamicCast<dot11s::IePeerManagement> ((*i)) == 0)
+ {
+ return false;
+ }
+ if (DynamicCast<dot11s::IePeerManagement> ((*j)) == 0)
+ {
+ return false;
+ }
+ if (!(*DynamicCast<dot11s::IePeerManagement> ((*i)) == *DynamicCast<dot11s::IePeerManagement> ((*j))))
+ {
+ return false;
+ }
+ break;
+ case IE11S_BEACON_TIMING:
+ if (DynamicCast<dot11s::IeBeaconTiming> ((*i)) == 0)
+ {
+ return false;
+ }
+ if (DynamicCast<dot11s::IeBeaconTiming> ((*j)) == 0)
+ {
+ return false;
+ }
+ if (!(*DynamicCast<dot11s::IeBeaconTiming> ((*i)) == *DynamicCast<dot11s::IeBeaconTiming> ((*j))))
+ {
+ return false;
+ }
+ break;
+ case IE11S_RANN:
+ if (DynamicCast<dot11s::IeRann> ((*i)) == 0)
+ {
+ return false;
+ }
+ if (DynamicCast<dot11s::IeRann> ((*j)) == 0)
+ {
+ return false;
+ }
+ if (!(*DynamicCast<dot11s::IeRann> ((*i)) == *DynamicCast<dot11s::IeRann> ((*j))))
+ {
+ return false;
+ }
+ break;
+ case IE11S_PREQ:
+ if (DynamicCast<dot11s::IePreq> ((*i)) == 0)
+ {
+ return false;
+ }
+ if (DynamicCast<dot11s::IePreq> ((*j)) == 0)
+ {
+ return false;
+ }
+ if (!(*DynamicCast<dot11s::IePreq> ((*i)) == *DynamicCast<dot11s::IePreq> ((*j))))
+ {
+ return false;
+ }
+ break;
+ case IE11S_PREP:
+ if (DynamicCast<dot11s::IePrep> ((*i)) == 0)
+ {
+ return false;
+ }
+ if (DynamicCast<dot11s::IePrep> ((*j)) == 0)
+ {
+ return false;
+ }
+ if (!(*DynamicCast<dot11s::IePrep> ((*i)) == *DynamicCast<dot11s::IePrep> ((*j))))
+ {
+ return false;
+ }
+
+ break;
+ case IE11S_PERR:
+ if (DynamicCast<dot11s::IePerr> ((*i)) == 0)
+ {
+ return false;
+ }
+ if (DynamicCast<dot11s::IePerr> ((*j)) == 0)
+ {
+ return false;
+ }
+ if (!(*DynamicCast<dot11s::IePerr> ((*i)) == *DynamicCast<dot11s::IePerr> ((*j))))
+ {
+ return false;
+ }
+ break;
+ case IE11S_MESH_PEERING_PROTOCOL_VERSION:
+ break;
+ default:
+ NS_FATAL_ERROR ("Information element " << (uint16_t) id << " is not implemented");
+ return false;
+ }
+ }
+ return true;
+}
+#ifdef RUN_SELF_TESTS
+
+/// Built-in self test for WifiInformationElementVector
+struct WifiInformationElementVectorBist : public Test
+{
+ WifiInformationElementVectorBist () :
+ Test ("Mesh/WifiInformationElementVector")
+ {
+ };
+ virtual bool
+ RunTests ();
+};
+
+/// Test instance
+static WifiInformationElementVectorBist g_IePrepBist;
+
+bool
+WifiInformationElementVectorBist::RunTests ()
+{
+ bool result = true;
+ WifiInformationElementVector vector;
+ {
+ //Mesh ID test
+ Ptr<dot11s::IeMeshId> meshId = Create<dot11s::IeMeshId> ("qwerty");
+ vector.AddInformationElement (meshId);
+ }
+ {
+ Ptr<dot11s::IeConfiguration> config = Create<dot11s::IeConfiguration> ();
+ vector.AddInformationElement (config);
+ }
+ {
+ Ptr<dot11s::IeLinkMetricReport> report = Create<dot11s::IeLinkMetricReport> (123456);
+ vector.AddInformationElement (report);
+ }
+ {
+ Ptr<dot11s::IePeerManagement> peerMan1 = Create<dot11s::IePeerManagement> ();
+ peerMan1->SetPeerOpen (1);
+ Ptr<dot11s::IePeerManagement> peerMan2 = Create<dot11s::IePeerManagement> ();
+ peerMan2->SetPeerConfirm (1, 2);
+ Ptr<dot11s::IePeerManagement> peerMan3 = Create<dot11s::IePeerManagement> ();
+ peerMan3->SetPeerClose (1, 2, dot11s::REASON11S_MESH_CAPABILITY_POLICY_VIOLATION);
+ vector.AddInformationElement (peerMan1);
+ vector.AddInformationElement (peerMan2);
+ vector.AddInformationElement (peerMan3);
+ }
+ {
+ Ptr<dot11s::IeBeaconTiming> beaconTiming = Create<dot11s::IeBeaconTiming> ();
+ beaconTiming->AddNeighboursTimingElementUnit (1, Seconds (1.0), Seconds (4.0));
+ beaconTiming->AddNeighboursTimingElementUnit (2, Seconds (2.0), Seconds (3.0));
+ beaconTiming->AddNeighboursTimingElementUnit (3, Seconds (3.0), Seconds (2.0));
+ beaconTiming->AddNeighboursTimingElementUnit (4, Seconds (4.0), Seconds (1.0));
+ vector.AddInformationElement (beaconTiming);
+ }
+ {
+ Ptr<dot11s::IeRann> rann = Create<dot11s::IeRann> ();
+ rann->SetFlags (1);
+ rann->SetHopcount (2);
+ rann->SetTTL (4);
+ rann->DecrementTtl ();
+ NS_TEST_ASSERT_EQUAL (rann->GetTtl (), 3);
+ rann->SetOriginatorAddress (Mac48Address ("11:22:33:44:55:66"));
+ rann->SetDestSeqNumber (5);
+ rann->SetMetric (6);
+ rann->IncrementMetric (2);
+ NS_TEST_ASSERT_EQUAL (rann->GetMetric (), 8);
+ vector.AddInformationElement (rann);
+ }
+ {
+ Ptr<dot11s::IePreq> preq = Create<dot11s::IePreq> ();
+ preq->SetHopcount (0);
+ preq->SetTTL (1);
+ preq->SetPreqID (2);
+ preq->SetOriginatorAddress (Mac48Address ("11:22:33:44:55:66"));
+ preq->SetOriginatorSeqNumber (3);
+ preq->SetLifetime (4);
+ preq->AddDestinationAddressElement (false, false, Mac48Address ("11:11:11:11:11:11"), 5);
+ preq->AddDestinationAddressElement (false, false, Mac48Address ("22:22:22:22:22:22"), 6);
+ vector.AddInformationElement (preq);
+ }
+ {
+ Ptr<dot11s::IePrep> prep = Create<dot11s::IePrep> ();
+ prep->SetFlags (12);
+ prep->SetHopcount (11);
+ prep->SetTtl (10);
+ prep->SetDestinationAddress (Mac48Address ("11:22:33:44:55:66"));
+ prep->SetDestinationSeqNumber (123);
+ prep->SetLifetime (5000);
+ prep->SetMetric (4321);
+ prep->SetOriginatorAddress (Mac48Address ("33:00:22:00:11:00"));
+ prep->SetOriginatorSeqNumber (666);
+ vector.AddInformationElement (prep);
+ }
+ {
+ Ptr<dot11s::IePerr> perr = Create<dot11s::IePerr> ();
+ dot11s::IePerr::FailedDestination dest;
+ dest.destination = Mac48Address ("11:22:33:44:55:66");
+ dest.seqnum = 1;
+ perr->AddAddressUnit (dest);
+ dest.destination = Mac48Address ("10:20:30:40:50:60");
+ dest.seqnum = 2;
+ perr->AddAddressUnit (dest);
+ dest.destination = Mac48Address ("01:02:03:04:05:06");
+ dest.seqnum = 3;
+ perr->AddAddressUnit (dest);
+ vector.AddInformationElement (perr);
+ }
+ Ptr<Packet> packet = Create<Packet> ();
+ packet->AddHeader (vector);
+ WifiInformationElementVector resultVector;
+ packet->RemoveHeader (resultVector);
+ NS_TEST_ASSERT (vector == resultVector);
+
+ return result;
+}
+
+#endif // RUN_SELF_TESTS
+} //namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/wifi-information-element-vector.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,148 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Authors: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko.iitp.ru>
+ */
+
+#ifndef IE_VECTOR_H
+#define IE_VECTOR_H
+
+#include "ns3/header.h"
+
+namespace ns3 {
+class Packet;
+/**
+ * \ingroup mesh
+ *
+ * \brief Enum of all known information element id (aka tags).
+ *
+ * For now only 802.11s (mesh) related elements are supported here (so 11S prefix),
+ * but this can change in future.
+ *
+ * Note that 802.11s element ids are not yet officially assigned, we use ones
+ * compatible with open80211s (http://o11s.org/) implementation.
+ */
+enum WifiElementId {
+ /* begin of open80211s-compatible IDs */
+ IE11S_MESH_CONFIGURATION = 51,
+ IE11S_MESH_ID = 52,
+ /* end of open80211s-compatible IDs */
+ IE11S_LINK_METRIC_REPORT = 20,
+ IE11S_CONGESTION_NOTIFICATION,
+ /* begin of open80211s-compatible IDs */
+ IE11S_PEERING_MANAGEMENT = 55,
+ /* end of open80211s-compatible IDs */
+ IE11S_SUPP_MBSS_REG_CLASSES_CHANNELS = 23,
+ IE11S_MESH_CHANNEL_SWITCH_ANNOUNCEMENT,
+ IE11S_MESH_TIM,
+ IE11S_AWAKE_WINDOW,
+ IE11S_BEACON_TIMING,
+ IE11S_MCCAOP_SETUP_REQUEST,
+ IE11S_MCCAOP_SETUP_REPLY,
+ IE11S_MCCAOP_ADVERTISEMENT,
+ IE11S_MCCAOP_RESERVATION_TEARDOWN,
+ IE11S_PORTAL_ANNOUNCEMENT,
+ IE11S_RANN = 67,
+ /* begin of open80211s-compatible IDs */
+ IE11S_PREQ = 68,
+ IE11S_PREP = 69,
+ IE11S_PERR = 70,
+ /* end of open80211s-compatible IDs */
+ IE11S_PROXY_UPDATE = 37,
+ IE11S_PROXY_UPDATE_CONFIRMATION,
+ IE11S_ABBREVIATED_HANDSHAKE,
+ IE11S_MESH_PEERING_PROTOCOL_VERSION = 74,
+};
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Information element, as defined in 802.11-2007 standard
+ *
+ * Elements are defined to have a common general format consisting of a 1 octet Element ID field, a 1 octet
+ * length field, and a variable-length element-specific information field. Each element is assigned a unique
+ * Element ID as defined in this standard. The Length field specifies the number of octets in the Information
+ * field.
+ */
+class WifiInformationElement : public RefCountBase
+{
+public:
+ ///\name Each subclass must implement
+ //\{
+ virtual void Print (std::ostream &os) const = 0;
+ /// Own unique Element ID
+ virtual WifiElementId ElementId () const = 0;
+ /// Length of serialized information
+ virtual uint8_t GetInformationSize () const = 0;
+ /// Serialize information
+ virtual void SerializeInformation (Buffer::Iterator start) const = 0;
+ /// Deserialize information
+ virtual uint8_t DeserializeInformation (Buffer::Iterator start, uint8_t length) = 0;
+ //\}
+
+ /// Compare information elements using Element ID
+ friend bool operator< (WifiInformationElement const & a, WifiInformationElement const & b);
+};
+
+/// Compare information elements using Element ID
+bool operator< (WifiInformationElement const & a, WifiInformationElement const & b);
+
+/**
+ * \ingroup mesh
+ *
+ * \brief Information element vector
+ *
+ * Implements a vector of WifiInformationElement's
+ */
+class WifiInformationElementVector : public Header
+{
+public:
+ WifiInformationElementVector ();
+ ~WifiInformationElementVector ();
+ ///\name Inherited from Header
+ //\{
+ static TypeId GetTypeId ();
+ TypeId GetInstanceTypeId () const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+ virtual void Print (std::ostream &os) const;
+ //\}
+ /**
+ * \brief Needed when you try to deserialize a lonely IE inside other header
+ * \param start is the start of the buffer
+ * \return deserialized bytes
+ */
+ virtual uint32_t DeserializeSingleIe (Buffer::Iterator start);
+ void SetMaxSize (uint16_t size);
+ typedef std::vector<Ptr<WifiInformationElement> >::iterator Iterator;
+ Iterator Begin ();
+ Iterator End ();
+ bool AddInformationElement (Ptr<WifiInformationElement> element);
+ Ptr<WifiInformationElement> FindFirst (enum WifiElementId id) const;
+private:
+ uint32_t GetSize () const;
+ typedef std::vector<Ptr<WifiInformationElement> > IE_VECTOR;
+ IE_VECTOR m_elements;
+ /// Size in bytes (actually, max packet length)
+ uint16_t m_maxSize;
+ friend bool operator== (const WifiInformationElementVector & a, const WifiInformationElementVector & b);
+};
+bool operator== (const WifiInformationElementVector & a, const WifiInformationElementVector & b);
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/wscript Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,23 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_module('mesh', ['wifi', 'dot11s'])
+
+ obj.source = [
+ 'wifi-information-element-vector.cc',
+ 'mesh-point-device.cc',
+ 'mesh-l2-routing-protocol.cc',
+ 'mesh-wifi-beacon.cc',
+ 'mesh-wifi-interface-mac.cc',
+ ]
+ headers = bld.new_task_gen('ns3header')
+ headers.module = 'mesh'
+ headers.source = [
+ 'wifi-information-element-vector.h',
+ 'mesh-point-device.h',
+ 'mesh-l2-routing-protocol.h',
+ 'mesh-wifi-beacon.h',
+ 'mesh-wifi-interface-mac.h',
+ 'mesh-wifi-interface-mac-plugin.h',
+ 'mesh-stack-installer.h',
+ ]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/mesh-helper.cc Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+#include "mesh-helper.h"
+#include "ns3/simulator.h"
+#include "ns3/mesh-point-device.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-wifi-interface-mac.h"
+namespace ns3
+{
+MeshHelper::MeshHelper () :
+ m_nInterfaces (1),
+ m_spreadChannelPolicy (ZERO_CHANNEL),
+ m_stack (0),
+ m_standard (WIFI_PHY_STANDARD_80211a)
+{
+}
+void
+MeshHelper::SetSpreadInterfaceChannels (enum ChannelPolicy policy)
+{
+ m_spreadChannelPolicy = policy;
+}
+void
+MeshHelper::SetStackInstaller (std::string type,
+ std::string n0, const AttributeValue &v0,
+ std::string n1, const AttributeValue &v1,
+ std::string n2, const AttributeValue &v2,
+ std::string n3, const AttributeValue &v3,
+ std::string n4, const AttributeValue &v4,
+ std::string n5, const AttributeValue &v5,
+ std::string n6, const AttributeValue &v6,
+ std::string n7, const AttributeValue &v7)
+{
+ m_stackFactory.SetTypeId (type);
+ m_stackFactory.Set (n0, v0);
+ m_stackFactory.Set (n1, v1);
+ m_stackFactory.Set (n2, v2);
+ m_stackFactory.Set (n3, v3);
+ m_stackFactory.Set (n4, v4);
+ m_stackFactory.Set (n5, v5);
+ m_stackFactory.Set (n6, v6);
+ m_stackFactory.Set (n7, v7);
+
+ m_stack = m_stackFactory.Create<MeshStack> ();
+ if (m_stack == 0)
+ {
+ NS_FATAL_ERROR ("Stack has not been created: " << type);
+ }
+}
+
+void
+MeshHelper::SetNumberOfInterfaces (uint32_t nInterfaces)
+{
+ m_nInterfaces = nInterfaces;
+}
+NetDeviceContainer
+MeshHelper::Install (const WifiPhyHelper &phyHelper, NodeContainer c) const
+{
+ NetDeviceContainer devices;
+ NS_ASSERT (m_stack != 0);
+ for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+ {
+ Ptr<Node> node = *i;
+ // Create a mesh point device
+ Ptr<MeshPointDevice> mp = CreateObject<MeshPointDevice> ();
+ node->AddDevice (mp);
+ // Create wifi interfaces (single interface by default)
+ for (uint32_t i = 0; i < m_nInterfaces; ++i)
+ {
+ uint32_t channel = 0;
+ if (m_spreadChannelPolicy == ZERO_CHANNEL)
+ {
+ channel = 0;
+ }
+ if (m_spreadChannelPolicy == SPREAD_CHANNELS)
+ {
+ channel = i * 5;
+ }
+ Ptr<WifiNetDevice> iface = CreateInterface (phyHelper, node, channel);
+ mp->AddInterface (iface);
+ }
+ if (!m_stack->InstallStack (mp))
+ {
+ NS_FATAL_ERROR ("Stack is not installed!");
+ }
+ devices.Add (mp);
+ }
+ return devices;
+}
+MeshHelper
+MeshHelper::Default (void)
+{
+ MeshHelper helper;
+ helper.SetMacType ();
+ helper.SetRemoteStationManager ("ns3::ArfWifiManager");
+ helper.SetSpreadInterfaceChannels (SPREAD_CHANNELS);
+ return helper;
+}
+
+void
+MeshHelper::SetMacType (std::string n0, const AttributeValue &v0,
+ std::string n1, const AttributeValue &v1,
+ std::string n2, const AttributeValue &v2,
+ std::string n3, const AttributeValue &v3,
+ std::string n4, const AttributeValue &v4,
+ std::string n5, const AttributeValue &v5,
+ std::string n6, const AttributeValue &v6,
+ std::string n7, const AttributeValue &v7)
+{
+ m_mac.SetTypeId ("ns3::MeshWifiInterfaceMac");
+ m_mac.Set (n0, v0);
+ m_mac.Set (n1, v1);
+ m_mac.Set (n2, v2);
+ m_mac.Set (n3, v3);
+ m_mac.Set (n4, v4);
+ m_mac.Set (n5, v5);
+ m_mac.Set (n6, v6);
+ m_mac.Set (n7, v7);
+}
+void
+MeshHelper::SetRemoteStationManager (std::string type,
+ std::string n0, const AttributeValue &v0,
+ std::string n1, const AttributeValue &v1,
+ std::string n2, const AttributeValue &v2,
+ std::string n3, const AttributeValue &v3,
+ std::string n4, const AttributeValue &v4,
+ std::string n5, const AttributeValue &v5,
+ std::string n6, const AttributeValue &v6,
+ std::string n7, const AttributeValue &v7)
+{
+ m_stationManager = ObjectFactory ();
+ m_stationManager.SetTypeId (type);
+ m_stationManager.Set (n0, v0);
+ m_stationManager.Set (n1, v1);
+ m_stationManager.Set (n2, v2);
+ m_stationManager.Set (n3, v3);
+ m_stationManager.Set (n4, v4);
+ m_stationManager.Set (n5, v5);
+ m_stationManager.Set (n6, v6);
+ m_stationManager.Set (n7, v7);
+}
+void
+MeshHelper::SetStandard (enum WifiPhyStandard standard)
+{
+ m_standard = standard;
+}
+
+Ptr<WifiNetDevice>
+MeshHelper::CreateInterface (const WifiPhyHelper &phyHelper, Ptr<Node> node, uint16_t channelId) const
+{
+ Ptr<WifiNetDevice> device = CreateObject<WifiNetDevice> ();
+
+ Ptr<MeshWifiInterfaceMac> mac = m_mac.Create<MeshWifiInterfaceMac> ();
+ NS_ASSERT (mac != 0);
+ mac->SetSsid (Ssid ());
+ Ptr<WifiRemoteStationManager> manager = m_stationManager.Create<WifiRemoteStationManager> ();
+ NS_ASSERT (manager != 0);
+ Ptr<WifiPhy> phy = phyHelper.Create (node, device);
+ mac->SetAddress (Mac48Address::Allocate ());
+ mac->ConfigureStandard (m_standard);
+ phy->ConfigureStandard (m_standard);
+ device->SetMac (mac);
+ device->SetPhy (phy);
+ device->SetRemoteStationManager (manager);
+ node->AddDevice (device);
+ mac->SwitchFrequencyChannel (channelId);
+ return device;
+}
+void
+MeshHelper::Report (const ns3::Ptr<ns3::NetDevice>& device, std::ostream& os)
+{
+ NS_ASSERT (m_stack != 0);
+ Ptr<MeshPointDevice> mp = device->GetObject<MeshPointDevice> ();
+ NS_ASSERT (mp != 0);
+ std::vector<Ptr<NetDevice> > ifaces = mp->GetInterfaces ();
+ os << "<MeshPointDevice time=\"" << Simulator::Now ().GetSeconds () << "\" address=\""
+ << Mac48Address::ConvertFrom (mp->GetAddress ()) << "\">\n";
+ m_stack->Report (mp, os);
+ os << "</MeshPointDevice>\n";
+}
+void
+MeshHelper::ResetStats (const ns3::Ptr<ns3::NetDevice>& device)
+{
+ NS_ASSERT (m_stack != 0);
+ Ptr<MeshPointDevice> mp = device->GetObject<MeshPointDevice> ();
+ NS_ASSERT (mp != 0);
+ m_stack->ResetStats (mp);
+}
+} //namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/mesh-helper.h Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,149 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008,2009 IITP RAS
+ *
+ * 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: Kirill Andreev <andreev@iitp.ru>
+ * Pavel Boyko <boyko@iitp.ru>
+ */
+
+
+#ifndef MESH_HELPER_H
+#define MESH_HELPER_H
+
+#include "ns3/wifi-helper.h"
+#include "ns3/mesh-stack-installer.h"
+
+namespace ns3 {
+
+class WifiChannel;
+
+/**
+ * \ingroup dot11s
+ *
+ * \brief Helper to create IEEE 802.11s mesh networks
+ */
+class MeshHelper
+{
+public:
+ MeshHelper ();
+ static MeshHelper
+ Default ();
+ /**
+ * \param type the type of ns3::WifiMac to create.
+ * \param n%d the name of the attribute to set
+ * \param v%d the value of the attribute to set
+ *
+ * All the attributes specified in this method should exist
+ * in the requested mac.
+ */
+ void SetMacType (std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+ std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+ std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+ std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+ std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+ std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+ std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+ std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+ /**
+ * \param type the type of ns3::WifiRemoteStationManager to create.
+ * \param n%d the name of the attribute to set
+ * \param v%d the value of the attribute to set
+ *
+ * All the attributes specified in this method should exist
+ * in the requested station manager.
+ */
+ void
+ SetRemoteStationManager (std::string type,
+ std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+ std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+ std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+ std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+ std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+ std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+ std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+ std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+ /**
+ * Set PHY standard
+ */
+ void SetStandard (enum WifiPhyStandard standard);
+ void SetMeshId (std::string s);
+ /**
+ * \brief Spread/not spread frequency channels of MP interfaces.
+ *
+ * If set to true different non-overlaping 20MHz frequency
+ * channels will be assigned to different mesh point interfaces.
+ */
+ enum ChannelPolicy
+ {
+ SPREAD_CHANNELS,
+ ZERO_CHANNEL
+ };
+ void SetSpreadInterfaceChannels (ChannelPolicy);
+ /**
+ * \brief Set a number of interfaces in a mesh network
+ * \param nInterfaces is the number of interfaces
+ */
+ void SetNumberOfInterfaces (uint32_t nInterfaces);
+
+ /**
+ * \brief Install 802.11s mesh device & protocols on given node list
+ *
+ * \param phy Wifi PHY helper
+ * \param nodes List of nodes to install
+ * \param roots List of root mesh points
+ * \param nInterfaces Number of mesh point radio interfaces (= WiFi NICs)
+ *
+ * \return list of created mesh point devices, see MeshPointDevice
+ */
+ NetDeviceContainer
+ Install (const WifiPhyHelper &phyHelper, NodeContainer c) const;
+ /**
+ * \param type the type of ns3::MeshStack.
+ *
+ * All the attributes specified in this method should exist
+ * in the requested station manager.
+ */
+ void SetStackInstaller (std::string type,
+ std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
+ std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+ std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+ std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+ std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+ std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+ std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+ std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
+ void Report (const ns3::Ptr<ns3::NetDevice>&, std::ostream&);
+ void ResetStats (const ns3::Ptr<ns3::NetDevice>&);
+private:
+ /**
+ * \returns a WifiNetDevice with ready-to-use interface
+ */
+ Ptr<WifiNetDevice> CreateInterface (const WifiPhyHelper &phyHelper, Ptr<Node> node, uint16_t channelId) const;
+ uint32_t m_nInterfaces;
+ ChannelPolicy m_spreadChannelPolicy;
+ Ptr<MeshStack> m_stack;
+ ObjectFactory m_stackFactory;
+ ///\name Interface factory
+ ///\{
+ ObjectFactory m_mac;
+ ObjectFactory m_stationManager;
+ enum WifiPhyStandard m_standard;
+ ///\}
+};
+} //namespace ns3
+
+#endif /* MESH_HELPER_H */
+
--- a/src/helper/wscript Tue Aug 25 08:52:57 2009 +0200
+++ b/src/helper/wscript Wed Aug 26 15:29:03 2009 +0400
@@ -28,6 +28,7 @@
'ipv4-global-routing-helper.cc',
'ipv4-list-routing-helper.cc',
'ipv4-routing-helper.cc',
+ 'mesh-helper.cc',
'athstats-helper.cc',
'ipv6-address-helper.cc',
'ipv6-interface-container.cc',
@@ -65,6 +66,7 @@
'ipv4-global-routing-helper.h',
'ipv4-list-routing-helper.h',
'ipv4-routing-helper.h',
+ 'mesh-helper.h',
'athstats-helper.h',
'ipv6-address-helper.h',
'ipv6-interface-container.h',
--- a/src/wscript Tue Aug 25 08:52:57 2009 +0200
+++ b/src/wscript Wed Aug 26 15:29:03 2009 +0400
@@ -36,6 +36,9 @@
'helper',
'contrib/stats',
'applications/v4ping',
+ 'devices/mesh',
+ 'devices/mesh/dot11s',
+ 'devices/mesh/flame',
'applications/ping6',
'applications/radvd',
)