Merge with code.nsnam.org
authorKirill Andreev <andreev@iitp.ru>
Wed, 26 Aug 2009 15:29:03 +0400
changeset 5166 9d48acef10b3
parent 5165 08d3bef3b477 (diff)
parent 4740 34acfd7ad508 (current diff)
child 5167 a3ede758b713
Merge with code.nsnam.org
AUTHORS
examples/wscript
src/common/wscript
src/devices/wifi/wifi-mac-header.cc
src/devices/wifi/wifi-remote-station-manager.cc
src/devices/wifi/wifi-remote-station-manager.h
src/helper/wscript
src/internet-stack/sgi-hashmap.h
src/internet-stack/tcp-socket-impl.cc
src/node/wscript
src/wscript
--- 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',
     )