Merge 802.11s code.
authorAndrey Mazo <mazo@iitp.ru>
Sat, 28 Feb 2009 14:21:05 +0300
changeset 4793 4f6a6772628e
parent 4244 7c98934dcccd
child 4794 ddefc6dd6d9b
Merge 802.11s code.
examples/mesh.cc
examples/wscript
src/devices/l2-routing/l2-routing-hwmp/hwmp-rtable.cc
src/devices/l2-routing/l2-routing-hwmp/hwmp-rtable.h
src/devices/l2-routing/l2-routing-hwmp/hwmp-state.cc
src/devices/l2-routing/l2-routing-hwmp/hwmp-state.h
src/devices/l2-routing/l2-routing-hwmp/hwmp.cc
src/devices/l2-routing/l2-routing-hwmp/hwmp.h
src/devices/l2-routing/l2-routing-hwmp/waf
src/devices/l2-routing/l2-routing-hwmp/wscript
src/devices/l2-routing/l2-routing-main/l2-routing-net-device.cc
src/devices/l2-routing/l2-routing-main/l2-routing-net-device.h
src/devices/l2-routing/l2-routing-main/waf
src/devices/l2-routing/l2-routing-main/wscript
src/devices/wifi/dca-txop.h
src/devices/wifi/dot11s-codes.h
src/devices/wifi/dot11s-parameters.cc
src/devices/wifi/dot11s-parameters.h
src/devices/wifi/dot11s-peer-management-element.cc
src/devices/wifi/dot11s-peer-management-element.h
src/devices/wifi/mesh-configuration-element.cc
src/devices/wifi/mesh-configuration-element.h
src/devices/wifi/mesh-mgt-headers.cc
src/devices/wifi/mesh-mgt-headers.h
src/devices/wifi/mesh-wifi-beacon-timing-element.cc
src/devices/wifi/mesh-wifi-beacon-timing-element.h
src/devices/wifi/mesh-wifi-mac.cc
src/devices/wifi/mesh-wifi-mac.h
src/devices/wifi/mesh-wifi-peer-manager.cc
src/devices/wifi/mesh-wifi-peer-manager.h
src/devices/wifi/mesh-wifi-perr-information-element.cc
src/devices/wifi/mesh-wifi-perr-information-element.h
src/devices/wifi/mesh-wifi-prep-information-element.cc
src/devices/wifi/mesh-wifi-prep-information-element.h
src/devices/wifi/mesh-wifi-preq-information-element.cc
src/devices/wifi/mesh-wifi-preq-information-element.h
src/devices/wifi/mesh-wifi-rann-information-element.cc
src/devices/wifi/mesh-wifi-rann-information-element.h
src/devices/wifi/mgt-headers.cc
src/devices/wifi/mgt-headers.h
src/devices/wifi/tx-statistics.cc
src/devices/wifi/tx-statistics.h
src/devices/wifi/wifi-mac-header.cc
src/devices/wifi/wifi-mac-header.h
src/devices/wifi/wifi-remote-station-manager.cc
src/devices/wifi/wifi-remote-station-manager.h
src/devices/wifi/wscript
src/helper/hwmp-helper.cc
src/helper/hwmp-helper.h
src/helper/mesh-wifi-helper.cc
src/helper/mesh-wifi-helper.h
src/helper/wscript
src/node/l2-routing-protocol.cc
src/node/l2-routing-protocol.h
src/node/wscript
src/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mesh.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,108 @@
+/* -*-  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>
+ *          Evgeny Khorov <horov@frtk.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/mobility-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("TestMeshScript");
+
+int
+main(int argc, char *argv[])
+{
+	// Creating square topology with nNodes x nNodes grid:
+	int			xSize		=	5;
+	int         ySize       =   5;
+	double			step		=	100.0;	//Grid with one-hop edge
+	double			randomStart	=	0.1;	//One beacon interval
+	NodeContainer		nodes;
+	CommandLine		cmd;
+	MobilityHelper		mobility;
+	MeshWifiHelper		wifi;
+	NetDeviceContainer	meshDevices;
+	// Defining a size of our network:
+	cmd.AddValue("x-size", "Number of nodes in a row grid", xSize);
+	cmd.AddValue("y-size", "Number of rows in a grid", ySize);
+	cmd.AddValue("step", "Size of edge in our grid", step);
+	cmd.AddValue("start", "Random start parameter", randomStart);
+        cmd.Parse (argc, argv);
+	NS_LOG_DEBUG("Grid:"<<xSize<<"*"<<ySize);
+	// Creating nodes:
+	nodes.Create (ySize*xSize);
+
+	// Setting channel:
+	YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+	YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+	wifiPhy.SetChannel (wifiChannel.Create ());
+	// Setting Wifi:
+	//wifi.SetPhy("ns3::WifiPhy");
+	wifi.SetRemoteStationManager("ns3::AarfWifiManager");
+	Ssid ssid	=	Ssid("MyMeSH");
+	wifi.SetMac ("ns3::MeshWifiMac",
+			"Ssid", SsidValue (ssid),
+			"RandomStart", TimeValue (Seconds (randomStart))
+			);
+        wifi.SetPeerLinkManager ("ns3::WifiPeerManager");
+        wifi.SetL2RoutingProtocol ("ns3::Hwmp");
+        wifi.SetL2RoutingNetDevice ("ns3::L2RoutingNetDevice");
+	meshDevices	=	wifi.Install (wifiPhy,nodes,1);
+	// Installing Mobility.
+	mobility.SetPositionAllocator
+		("ns3::GridPositionAllocator",
+		 "MinX", DoubleValue (0.0),
+		 "MinY", DoubleValue (0.0),
+		 "DeltaX", DoubleValue (step),
+                 "DeltaY", DoubleValue (step),
+		 "GridWidth", UintegerValue (xSize),
+		 "LayoutType", StringValue("RowFirst"));
+	mobility.SetMobilityModel ("ns3::StaticMobilityModel");
+	mobility.Install (nodes);
+
+	// Setting Internet Stack:
+	InternetStackHelper stack;
+	stack.Install(nodes);
+	Ipv4AddressHelper address;
+	address.SetBase ("10.1.1.0", "255.255.255.0");
+	Ipv4InterfaceContainer interfaces = address.Assign (meshDevices);
+	UdpEchoServerHelper echoServer (9);
+	ApplicationContainer serverApps = echoServer.Install (nodes.Get (0));
+	serverApps.Start (Seconds (1.0));
+	serverApps.Stop (Seconds (10.0));
+	UdpEchoClientHelper echoClient (interfaces.GetAddress (0), 9);
+	echoClient.SetAttribute ("MaxPackets", UintegerValue (1000));
+	echoClient.SetAttribute ("Interval", TimeValue (Seconds (0.001)));
+	echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
+	ApplicationContainer clientApps = echoClient.Install (nodes.Get (1));
+	clientApps.Start (Seconds (2.0));
+	clientApps.Stop (Seconds (10.0));
+	//end
+	Simulator::Stop (Seconds (10.0));
+	Simulator::Run();
+	Simulator::Destroy();
+	return 0;
+}
--- a/examples/wscript	Wed Feb 25 12:27:00 2009 -0500
+++ b/examples/wscript	Sat Feb 28 14:21:05 2009 +0300
@@ -120,6 +120,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/l2-routing/l2-routing-hwmp/hwmp-rtable.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,282 @@
+/* -*-  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/ptr.h"
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "hwmp-rtable.h"
+
+NS_LOG_COMPONENT_DEFINE ("HwmpRtable");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (HwmpRtable);
+
+TypeId
+HwmpRtable::GetTypeId(void)
+{
+	static TypeId tid = TypeId ("ns3::HwmpRtable")
+		.SetParent<Object> ()
+		.AddConstructor<HwmpRtable> ();
+	return tid;
+
+}
+
+HwmpRtable::HwmpRtable()
+{
+}
+
+HwmpRtable::~HwmpRtable()
+{
+	DoDispose();
+}
+
+void
+HwmpRtable::DoDispose()
+{
+	NS_LOG_UNCOND("RTABLE DISPOSE STARTED");
+	m_routes.clear();
+	m_roots.clear();
+}
+
+void
+HwmpRtable::AddReactivePath(
+		Mac48Address	destination,
+		Mac48Address	retransmitter,
+		uint32_t	port,
+		uint32_t	metric,
+		Time		lifetime,
+		uint32_t	seqnum
+		)
+{
+	std::map<Mac48Address, struct ReactiveRoute, addrcmp>::iterator i = m_routes.find(destination);
+	if(i == m_routes.end())
+	{
+		struct ReactiveRoute newroute;
+		m_routes[destination] = newroute;
+	}
+	else
+	{
+		/**
+		 * if outport differs from stored, routing info is
+		 * actual and metric is worse - we ignore this
+		 * information
+		 */
+		if(
+				(i->second.port != port) &&
+				(i->second.metric < metric) &&
+				/**
+				 * The routing info is actual or it
+				 * was received from peer
+				 */
+				((i->second.whenExpire > Simulator::Now())||(i->second.whenExpire == Seconds(0)))
+				)
+			return;
+	}
+	i = m_routes.find(destination);
+	NS_ASSERT(i != m_routes.end());
+	i->second.retransmitter = retransmitter;
+	i->second.port = port;
+	i->second.metric = metric;
+	if(lifetime != Seconds(0))
+		i->second.whenExpire = MilliSeconds(Simulator::Now().GetMilliSeconds() + lifetime.GetMilliSeconds());
+	else
+		/**
+		 * Information about peer does not have lifetime
+		 */
+		i->second.whenExpire = Seconds(0);
+	i->second.seqnum = seqnum;
+}
+
+void
+HwmpRtable::AddProactivePath(
+		uint32_t	metric,
+		Mac48Address	root,
+		Mac48Address	retransmitter,
+		uint32_t	port,
+		Time		lifetime,
+		uint32_t	seqnum
+		)
+{
+	struct ProactiveRoute newroute;
+	m_roots[port] = newroute;
+	std::map<uint32_t,struct ProactiveRoute>::iterator i = m_roots.find(port);
+	NS_ASSERT(i != m_roots.end());
+	i->second.root = root;
+	i->second.retransmitter = retransmitter;
+	i->second.metric = metric;
+	i->second.whenExpire = MilliSeconds(Simulator::Now().GetMilliSeconds() + lifetime.GetMilliSeconds());
+	i->second.seqnum = seqnum;
+
+}
+
+void
+HwmpRtable::AddPrecursor(Mac48Address destination, uint32_t port, Mac48Address precursor)
+{
+	bool should_add = true;
+	std::map<Mac48Address, struct ReactiveRoute, addrcmp>::iterator i = m_routes.find(destination);
+	if((i != m_routes.end()) && (i->second.port == port))
+	{
+		for(unsigned int j = 0 ; j < i->second.precursors.size(); j ++)
+			if(i->second.precursors[j] == precursor)
+			{
+				should_add = false;
+				break;
+			}
+		if(should_add)
+			i->second.precursors.push_back(precursor);
+	}
+	std::map<uint32_t,struct ProactiveRoute>::iterator k = m_roots.find(port);
+	if(k!= m_roots.end())
+	{
+		for(unsigned int j = 0 ; j < k->second.precursors.size(); j ++)
+			if(k->second.precursors[j] == precursor)
+				return;
+		k->second.precursors.push_back(precursor);
+		return;
+	}
+}
+
+void
+HwmpRtable::DeleteProactivePath(uint32_t port)
+{
+	std::map<uint32_t,struct ProactiveRoute>::iterator j = m_roots.find(port);
+	if(j != m_roots.end())
+		m_roots.erase(j);
+
+}
+void
+HwmpRtable::DeleteProactivePath(Mac48Address root, uint32_t port)
+{
+	std::map<uint32_t,struct ProactiveRoute>::iterator j = m_roots.find(port);
+	if((j != m_roots.end())&&(j->second.root == root))
+		m_roots.erase(j);
+
+}
+
+void
+HwmpRtable::DeleteReactivePath(Mac48Address destination, uint32_t port)
+{
+	std::map<Mac48Address, struct ReactiveRoute, addrcmp>::iterator i = m_routes.find(destination);
+	if(i != m_routes.end())
+		if(i->second.port ==  port)
+			m_routes.erase(i);
+}
+
+struct HwmpRtable::LookupResult
+HwmpRtable::LookupReactive(Mac48Address destination)
+{
+	struct LookupResult result;
+	result.retransmitter = Mac48Address::GetBroadcast();
+	result.metric = MAX_METRIC;
+	result.ifIndex = PORT_ANY;
+	
+	std::map<Mac48Address, struct ReactiveRoute, addrcmp>::iterator i = m_routes.find(destination);
+	if(i == m_routes.end())
+		return result;
+	result.ifIndex = i->second.port;
+	//Seconds(0) means that this is routing
+	if(i->second.whenExpire < Simulator::Now())
+		if(i->second.retransmitter != destination)
+			return result;
+	result.retransmitter = i->second.retransmitter;
+	result.metric = i->second.metric;
+	result.seqnum = i->second.seqnum;
+	return result;
+}
+
+struct HwmpRtable::LookupResult
+HwmpRtable::LookupProactive(uint32_t port)
+{
+	struct LookupResult result;
+	result.retransmitter = Mac48Address::GetBroadcast();
+	result.metric = MAX_METRIC;
+	result.ifIndex = PORT_ANY;
+	std::map<uint32_t, struct ProactiveRoute, addrcmp>::iterator i = m_roots.find(port);
+	if(i == m_roots.end())
+		return result;
+	result.ifIndex = i->first;
+	if(i->second.whenExpire < Simulator::Now())
+		return result;
+	result.retransmitter = i->second.retransmitter;
+	result.metric = i->second.metric;
+	result.seqnum = i->second.seqnum;
+	return result;
+}
+
+std::vector<struct HwmpRtable::FailedDestination>
+HwmpRtable::GetUnreachableDestinations(Mac48Address peerAddress, uint32_t port)
+{
+	std::vector<struct FailedDestination> retval;
+	for(std::map<Mac48Address, struct ReactiveRoute, addrcmp>::iterator i = m_routes.begin(); i!= m_routes.end(); i++)
+		if((i->second.retransmitter == peerAddress)&&(i->second.port == port))
+		{
+			struct FailedDestination dst;
+			dst.destination = i->first;
+			i->second.seqnum ++;
+			dst.seqnum = i->second.seqnum;
+			retval.push_back(dst);
+		}
+	/**
+	 * Lookup a path to root
+	 */
+	std::map<uint32_t, struct ProactiveRoute, addrcmp>::iterator i = m_roots.find(port);
+	if((i != m_roots.end())&&(i->second.retransmitter == peerAddress))
+	{
+		struct FailedDestination dst;
+		dst.destination = i->second.root;
+		dst.seqnum = i->second.seqnum;
+		retval.push_back(dst);
+	}
+	return retval;
+}
+uint32_t
+HwmpRtable::RequestSeqnum(Mac48Address destination)
+{
+	std::map<Mac48Address, struct ReactiveRoute, addrcmp>::iterator i = m_routes.find(destination);
+	if(i == m_routes.end())
+		return 0;
+	return i->second.seqnum;
+}
+
+std::vector<Mac48Address>
+HwmpRtable::GetPrecursors(Mac48Address destination, uint32_t port)
+{
+	std::vector<Mac48Address> retval;
+	std::map<uint32_t, struct ProactiveRoute, addrcmp>::iterator root = m_roots.find(port);
+	if((root != m_roots.end()) &&(root->second.root == destination))
+	{
+		for(unsigned int i = 0; i < root->second.precursors.size(); i ++)
+			retval.push_back(root->second.precursors[i]);
+	}
+	std::map<Mac48Address, struct ReactiveRoute, addrcmp>::iterator route = m_routes.find(destination);
+	if( (route != m_routes.end()) && (route->second.port == port) )
+	{
+		for(unsigned int i = 0; i < route->second.precursors.size(); i ++)
+			retval.push_back(route->second.precursors[i]);
+	}
+	return retval;
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-hwmp/hwmp-rtable.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,125 @@
+/* -*-  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 <list>
+#include <map>
+#include "ns3/nstime.h"
+#include "ns3/mac48-address.h"
+#include "ns3/net-device.h"
+#include "ns3/event-id.h"
+#include "ns3/packet.h"
+namespace ns3 {
+
+
+	class HwmpRtable : public Object
+	{
+		public:
+			static TypeId	GetTypeId	(void);
+			HwmpRtable();
+			~HwmpRtable();
+			void	DoDispose();
+			void	AddReactivePath(
+					Mac48Address	destination,
+					Mac48Address	retransmitter,
+					uint32_t	port,
+					uint32_t	metric,
+					Time		lifetime,
+					uint32_t	seqnum
+					);
+			void	AddProactivePath(
+					uint32_t	metric,
+					Mac48Address	root,
+					Mac48Address	retransmitter,
+					uint32_t	port,
+					Time		lifetime,
+					uint32_t	seqnum
+					);
+			void	AddPrecursor(Mac48Address destination, uint32_t port, Mac48Address precursor);
+			void	DeleteProactivePath(uint32_t port);
+			void	DeleteProactivePath(Mac48Address root, uint32_t port);
+			void	DeleteReactivePath(Mac48Address destination, uint32_t port);
+			struct LookupResult
+			{
+				Mac48Address	retransmitter;
+				uint32_t	ifIndex;
+				uint32_t	metric;
+				uint32_t	seqnum;
+			};
+			struct LookupResult
+				LookupReactive(Mac48Address destination);
+			struct LookupResult
+				LookupProactive(uint32_t port);
+			//path error routines:
+			struct FailedDestination
+			{
+				Mac48Address	destination;
+				uint32_t	seqnum;
+			};
+			std::vector<struct FailedDestination>
+				GetUnreachableDestinations(Mac48Address peerAddress, uint32_t port);
+			uint32_t
+				RequestSeqnum(Mac48Address dst);
+			std::vector<Mac48Address>
+				GetPrecursors(Mac48Address destination, uint32_t port);
+			const static uint32_t	PORT_ANY = 0xffffffff;
+			const static uint32_t	MAX_METRIC = 0xffffffff;
+		private:
+			struct ReactiveRoute
+			{
+				Mac48Address retransmitter;
+				uint32_t port;
+				uint32_t metric;
+				Time whenExpire;
+				uint32_t seqnum;
+				std::vector<Mac48Address> precursors;
+			};
+			struct ProactiveRoute
+			{
+				Mac48Address root;
+				Mac48Address retransmitter;
+				uint32_t metric;
+				Time whenExpire;
+				uint32_t seqnum;
+				std::vector<Mac48Address> precursors;
+			};
+			struct addrcmp
+			{
+				bool operator()(const Mac48Address addr1, const Mac48Address addr2) const
+					    {
+						    uint8_t s1[6], s2[6];
+						    addr1.CopyTo(s1);
+						    addr2.CopyTo(s2);
+						    for(int i = 0; i < 6; i ++)
+							    if(s1[i] > s2[i])
+								    return true;
+						    return false;
+					    }
+			};
+			std::map<Mac48Address, struct ReactiveRoute, addrcmp>
+				m_routes;
+			std::map<uint32_t, struct ProactiveRoute>
+				m_roots;
+	};
+} //namespace ns3
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-hwmp/hwmp-state.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,539 @@
+/* -*-  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 "hwmp-state.h"
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/log.h"
+namespace ns3 {
+
+
+NS_LOG_COMPONENT_DEFINE ("HwmpState");
+TypeId
+HwmpState::GetTypeId (void)
+{
+	static TypeId tid = TypeId ("ns3::HwmpState")
+		.SetParent<Object> ()
+		.AddConstructor<HwmpState> ()
+		;
+	return tid;
+}
+
+HwmpState::HwmpState()
+{
+	m_myPreq = m_preqQueue.end();
+	m_preqId = 1;
+	m_myDsn = 1;
+	m_maxTtl = 10;
+	m_disabled = false;
+}
+void
+HwmpState::SetRequestRouteCallback(
+		Callback<struct HwmpRtable::LookupResult, const Mac48Address&> cb)
+{
+	m_requestRouteCallback = cb;
+}
+
+void
+HwmpState::SetRequestRootPathCallback(
+		Callback<struct HwmpRtable::LookupResult, uint32_t> cb)
+{
+	m_requestRootPathCallback = cb;
+}
+
+//Setting MAC
+void
+HwmpState::SetMac(Ptr<MeshWifiMac> mac)
+{
+	mac->SetPeerStatusCallback(MakeCallback(&HwmpState::PeerStatus, this));
+	mac->SetPreqReceivedCallback(MakeCallback(&HwmpState::ReceivePreq, this));
+	mac->SetPrepReceivedCallback(MakeCallback(&HwmpState::ReceivePrep, this));
+	mac->SetPerrReceivedCallback(MakeCallback(&HwmpState::ReceivePerr, this));
+	m_address = mac->GetAddress();
+	m_preqCallback = MakeCallback(&MeshWifiMac::SendPreq, mac);
+	m_prepCallback = MakeCallback(&MeshWifiMac::SendPrep, mac);
+	m_perrCallback = MakeCallback(&MeshWifiMac::SendPerr, mac);
+}
+HwmpState::~HwmpState()
+{
+	m_preqQueue.clear();
+}
+//Interaction with HWMP:
+void
+HwmpState::SetRoutingInfoCallback(
+		Callback<void, INFO> cb
+		)
+{
+	m_routingInfoCallback = cb;
+}
+
+void
+HwmpState::SetRetransmittersOfPerrCallback(
+		Callback<std::vector<Mac48Address>, std::vector<struct HwmpRtable::FailedDestination>, uint32_t> cb)
+{
+	m_retransmittersOfPerrCallback = cb;
+}
+
+void
+HwmpState::RequestDestination(Mac48Address dst)
+{
+	if(m_preqQueue.end() == m_myPreq)
+	{
+		WifiPreqInformationElement preq;
+		//fill PREQ:
+		preq.SetHopcount(0);
+		preq.SetTTL(m_maxTtl);
+		preq.SetPreqID(m_preqId++);
+		if(m_preqId == MAX_PREQ_ID)
+			m_preqId = 0;
+		preq.SetLifetime(TIME_TO_TU(dot11sParameters::dot11MeshHWMPactivePathTimeout));
+		preq.SetOriginatorSeqNumber(m_myDsn++);
+		if(m_myDsn == MAX_DSN)
+			m_myDsn = 0;
+		preq.SetOriginatorAddress(m_address);
+		preq.AddDestinationAddressElement(false, false, dst, 0); //DO = 0, RF = 0
+		if(m_preqTimer.IsRunning())
+		{
+			NS_LOG_DEBUG("No my preq");
+			m_preqQueue.push_back(preq);
+			//set iterator position to my preq:
+			m_myPreq = m_preqQueue.end() -1;
+		}
+		else
+		{
+			NS_LOG_DEBUG("Send PREQ now, "<<preq.GetPreqID()<<" destinations, now is "<<Simulator::Now());
+			m_preqCallback(preq);
+		NS_ASSERT(!m_preqTimer.IsRunning());
+			m_preqTimer = Simulator::Schedule(dot11sParameters::dot11MeshHWMPpreqMinInterval, &HwmpState::SendOnePreq, this);
+		}
+	}
+	else
+	{
+		NS_ASSERT(m_myPreq->GetOriginatorAddress() == m_address);
+		NS_LOG_DEBUG("add a destination "<<dst);
+		m_myPreq->AddDestinationAddressElement(false, false, dst, 0); //DO = 0, RF = 0
+	}
+}
+void
+HwmpState::SendPathError(std::vector<struct HwmpRtable::FailedDestination> destinations)
+{
+	std::vector<Mac48Address> receivers =  m_retransmittersOfPerrCallback(destinations, m_ifIndex);
+	NS_LOG_DEBUG("SendPathError started");
+	if(receivers.size()== 0)
+		return;
+	NS_LOG_DEBUG(m_address<<" Should Send PERR to");
+	for(unsigned int i = 0; i < receivers.size(); i ++)
+	{
+		AddPerrReceiver(receivers[i]);
+		NS_LOG_DEBUG(receivers[i]);
+	}
+	NS_LOG_DEBUG("To tel about failure with");
+	for(unsigned int i = 0; i < destinations.size(); i ++)
+	{
+		m_myPerr.AddAddressUnit(destinations[i]);
+		NS_LOG_DEBUG(destinations[i].destination);
+	}
+	if(!m_perrTimer.IsRunning())
+	{
+		m_perrCallback(m_myPerr,m_myPerrReceivers);
+		m_myPerr.ResetPerr();
+		m_perrTimer = Simulator::Schedule(dot11sParameters::dot11MeshHWMPperrMinInterval,&HwmpState::SendOnePerr,this);
+	}
+}
+//needed to fill routing information structure
+void
+HwmpState::SetAssociatedIfaceId(uint32_t interface)
+{
+	m_ifIndex = interface;
+}
+
+uint32_t
+HwmpState::GetAssociatedIfaceId()
+{
+	return m_ifIndex;
+}
+
+//Interaction with MAC:
+void
+HwmpState::ReceivePreq(WifiPreqInformationElement& preq,  const Mac48Address& from, const uint32_t& metric)
+{
+	if(m_disabled)
+		return;
+	if(preq.GetOriginatorAddress() == m_address)
+		return;
+	preq.DecrementTtl();
+	preq.IncrementMetric(metric);
+	if(preq.GetTtl() == 0)
+		return;
+	//acceptance cretirea:
+	std::map<Mac48Address, uint32_t, addrcmp>::iterator i = m_dsnDatabase.find(preq.GetOriginatorAddress());
+	if(i == m_dsnDatabase.end())
+	{
+		m_dsnDatabase[preq.GetOriginatorAddress()] = preq.GetOriginatorSeqNumber();
+		m_preqMetricDatabase[preq.GetOriginatorAddress()] = preq.GetMetric();
+	}
+	else
+	{
+		if(i->second > preq.GetOriginatorSeqNumber())
+			return;
+		if(i->second == preq.GetOriginatorSeqNumber())
+		{
+			//find metric
+			std::map<Mac48Address, uint32_t, addrcmp>::iterator j = 
+				m_preqMetricDatabase.find(preq.GetOriginatorAddress());
+			NS_ASSERT(j != m_dsnDatabase.end());
+			if(j->second <= preq.GetMetric())
+				return;
+		}
+		m_dsnDatabase[preq.GetOriginatorAddress()] = preq.GetOriginatorSeqNumber();
+		m_preqMetricDatabase[preq.GetOriginatorAddress()] = preq.GetMetric();
+	}
+	NS_LOG_DEBUG(
+			"PREQ from "<< preq.GetOriginatorAddress()
+			<<", at "<< m_address
+			<<", TTL ="<< (int)preq.GetTtl()
+			<<", metric = "<< preq.GetMetric()
+			<<", hopcount = "<< (int)preq.GetHopCount()
+			<<", preqId = "<< preq.GetPreqID()
+			<<", transmitter is "<<from);
+	//fill routingTable
+	INFO newInfo;
+	newInfo.me = m_address;
+	newInfo.destination = preq.GetOriginatorAddress();
+	newInfo.nextHop = from;
+	newInfo.metric = preq.GetMetric();
+	newInfo.lifetime = TU_TO_TIME(preq.GetLifetime());
+	newInfo.outPort = m_ifIndex;
+	newInfo.dsn = preq.GetOriginatorSeqNumber();
+	newInfo.type = INFO_PREQ;
+	//check if can answer:
+	std::vector<Ptr<DestinationAddressUnit> > destinations = preq.GetDestinationList ();
+	for(std::vector<Ptr<DestinationAddressUnit> >::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()));
+			NS_LOG_DEBUG("PROACTIVE PREQ RECEIVED");
+			newInfo.type = INFO_PROACTIVE;
+			m_routingInfoCallback(newInfo);
+			if(!preq.IsNeedNotPrep())
+			{
+				SendPrep(
+						preq.GetOriginatorAddress(),
+						m_address,
+						from,
+						preq.GetMetric(),
+						preq.GetOriginatorSeqNumber(),
+						m_myDsn ++,
+						preq.GetLifetime()
+						);
+				if(m_myDsn == MAX_DSN)
+					m_myDsn = 0;
+			}
+			break;
+		}
+		if((*i)->GetDestinationAddress()==m_address)
+		{
+			preq.DelDestinationAddressElement((*i)->GetDestinationAddress());
+			SendPrep(
+					preq.GetOriginatorAddress(),
+					m_address,
+					from,
+					0,
+					preq.GetOriginatorSeqNumber(),
+					m_myDsn++,
+					preq.GetLifetime()
+					);
+			if(m_myDsn == MAX_DSN)
+				m_myDsn = 0;
+			continue;
+		}
+		//check if can answer:
+		struct HwmpRtable::LookupResult result = m_requestRouteCallback((*i)->GetDestinationAddress());
+		if((!((*i)->IsDo())) && (result.retransmitter!=Mac48Address::GetBroadcast()))
+		{
+			//have a valid information and acn answer
+			if((*i)->IsRf())
+				(*i)->SetFlags(true, false); //DO = 1, RF = 0 (as it was)
+			else
+			{
+				//send a PREP and delete destination
+				preq.DelDestinationAddressElement((*i)->GetDestinationAddress());
+				SendPrep(
+						preq.GetOriginatorAddress(),
+						(*i)->GetDestinationAddress(),
+						result.retransmitter,
+						result.metric,
+						preq.GetOriginatorSeqNumber(),
+						result.seqnum,
+						preq.GetLifetime()
+						);
+				continue;
+			}
+		}
+	}
+	m_routingInfoCallback(newInfo);
+	//chack if must retransmit:
+	if(preq.GetDestCount() == 0)
+		return;
+	if(m_preqTimer.IsRunning())
+	{
+		m_preqQueue.push_back(preq);
+	}
+	else
+	{
+		m_preqCallback(preq);
+		NS_ASSERT(!m_preqTimer.IsRunning());
+		m_preqTimer = Simulator::Schedule(dot11sParameters::dot11MeshHWMPpreqMinInterval, &HwmpState::SendOnePreq, this);
+	}
+}
+
+void
+HwmpState::ReceivePrep(WifiPrepInformationElement& prep, const Mac48Address& from, const uint32_t& metric)
+{
+	if(m_disabled)
+		return;
+	prep.DecrementTtl();
+	prep.IncrementMetric(metric);
+	//acceptance cretirea:
+	std::map<Mac48Address, uint32_t, addrcmp>::iterator i = m_dsnDatabase.find(prep.GetDestinationAddress());
+	if(i == m_dsnDatabase.end())
+	{
+		m_dsnDatabase[prep.GetDestinationAddress()] = prep.GetDestinationSeqNumber();
+	}
+	else
+		if(i->second > prep.GetDestinationSeqNumber())
+			return;
+	//update routing info
+	struct HwmpRtable::LookupResult result = m_requestRouteCallback(prep.GetDestinationAddress());
+	if(result.retransmitter == Mac48Address::GetBroadcast())
+		//try to look for default route
+		result = m_requestRootPathCallback(m_ifIndex);
+	if((result.retransmitter == Mac48Address::GetBroadcast())&&(m_address != prep.GetDestinationAddress()))
+		return;
+	INFO newInfo;
+	newInfo.me = m_address;
+	newInfo.destination = prep.GetOriginatorAddress();
+	newInfo.source = prep.GetDestinationAddress();
+	newInfo.nextHop = from;
+	newInfo.metric = prep.GetMetric();
+	newInfo.lifetime = TU_TO_TIME(prep.GetLifetime());
+	newInfo.outPort = m_ifIndex;
+	newInfo.dsn = prep.GetOriginatorSeqNumber();
+	newInfo.prevHop = result.retransmitter;
+	newInfo.type = INFO_PREP;
+	NS_LOG_DEBUG("Path to "<<newInfo.source<<", i am "<<m_address<<", precursor is "<<from);
+	NS_LOG_DEBUG("Path to "<<newInfo.destination<<", i am "<<m_address<<", precursor is "<<result.retransmitter);
+	m_routingInfoCallback(newInfo);
+	if(prep.GetDestinationAddress() == m_address)
+	{
+		NS_LOG_DEBUG("Destination resolved"<<newInfo.destination);
+		return;
+	}
+	m_prepCallback(prep, result.retransmitter);
+}
+
+void
+HwmpState::ReceivePerr(WifiPerrInformationElement& perr, const Mac48Address& from)
+{
+	if(m_disabled)
+		return;
+	NS_LOG_DEBUG(m_address<<" RECEIVED PERR from "<<from);
+	/**
+	 * Check forwarding conditions:
+	 */
+	std::vector<HwmpRtable::FailedDestination> destinations = perr.GetAddressUnitVector();
+	for(unsigned int i = 0; i < destinations.size(); i ++)
+	{
+		/**
+		 * Lookup for a valid routing information
+		 */
+	struct HwmpRtable::LookupResult result = m_requestRouteCallback(destinations[i].destination);
+	if(
+			(result.retransmitter != from)
+			||(result.seqnum >= destinations[i].seqnum)
+	  )
+
+		perr.DeleteAddressUnit(destinations[i].destination);
+	}
+	NS_LOG_DEBUG("Retransmit "<<(int)perr.GetNumOfDest());
+	if(perr.GetNumOfDest() == 0)
+		return;
+	destinations = perr.GetAddressUnitVector();
+	SendPathError(destinations);
+}
+
+void
+HwmpState::PeerStatus(const Mac48Address peerAddress, const bool status, const uint32_t metric)
+{
+	INFO newInfo;
+	newInfo.me = m_address;
+	newInfo.destination = peerAddress;
+	newInfo.nextHop = peerAddress;
+	newInfo.metric = metric;
+	newInfo.outPort = m_ifIndex;
+	newInfo.dsn = 0;
+	if(status)
+		newInfo.type = INFO_NEW_PEER;
+	else
+		newInfo.type = INFO_FAILED_PEER;
+	m_routingInfoCallback(newInfo);
+}
+
+bool
+HwmpState::SetRoot()
+{
+#if 0
+	//TODO:: delete this lines!!!!!!!
+	if(m_address != Mac48Address("00:00:00:00:00:10"))
+		return false;
+	//TODO
+#endif
+	Simulator::Schedule(dot11sParameters::dot11MeshHWMPactiveRootTimeout, &HwmpState::SendProactivePreq, this);
+	return true;
+}
+
+void
+HwmpState::SendProactivePreq()
+{
+	NS_LOG_DEBUG("Sending proactive PREQ");
+	WifiPreqInformationElement preq;
+	//By default: must answer
+	preq.SetHopcount(0);
+	preq.SetTTL(m_maxTtl);
+	preq.SetPreqID(m_preqId++);
+	if(m_preqId == MAX_PREQ_ID)
+		m_preqId = 0;
+	preq.SetLifetime(TIME_TO_TU(dot11sParameters::dot11MeshHWMPpathToRootInterval));
+	preq.SetOriginatorSeqNumber(m_myDsn++);
+	if(m_myDsn == MAX_DSN)
+		m_myDsn = 0;
+	preq.SetOriginatorAddress(m_address);
+	preq.AddDestinationAddressElement(
+			true,
+			true,
+			Mac48Address::GetBroadcast()
+			,0);
+	if(m_preqTimer.IsRunning())
+		m_preqQueue.push_back(preq);
+	else
+	{
+		NS_LOG_DEBUG("Send now "<<preq.GetPreqID());
+		m_preqCallback(preq);
+		NS_ASSERT(!m_preqTimer.IsRunning());
+		m_preqTimer = Simulator::Schedule(dot11sParameters::dot11MeshHWMPpreqMinInterval, &HwmpState::SendOnePreq, this);
+	}
+	Simulator::Schedule(dot11sParameters::dot11MeshHWMPactiveRootTimeout, &HwmpState::SendProactivePreq, this);
+}
+
+void
+HwmpState::AddPerrReceiver(Mac48Address receiver)
+{
+	/**
+	 * add new vector of addresses to m_perrReceiversand check
+	 * duplicates
+	 */
+	for(unsigned int j = 0; j < m_myPerrReceivers.size(); j++)
+		if(m_myPerrReceivers[j] == receiver)
+			return;
+	m_myPerrReceivers.push_back(receiver);
+}
+
+void
+HwmpState::UnSetRoot()
+{
+}
+
+void
+HwmpState::Disable()
+{
+	m_disabled = true;
+}
+
+void
+HwmpState::Enable()
+{
+	m_disabled = false;
+}
+
+Mac48Address
+HwmpState::GetAddress()
+{
+	return m_address;
+}
+
+void
+HwmpState::SendOnePreq()
+{
+	if(m_preqQueue.size() == 0)
+		return;
+	if(m_myPreq == m_preqQueue.begin())
+		m_myPreq == m_preqQueue.end();
+	WifiPreqInformationElement preq = m_preqQueue[0];
+	NS_LOG_DEBUG(
+			"Sending PREQ from "<<preq.GetOriginatorAddress() <<
+			" destinations are  "<<(int)preq.GetDestCount()<<
+			", at "<<Simulator::Now()<<
+			", store in queue "<<m_preqQueue.size()<<
+			" preqs"<<", I am "<<m_address);
+	m_preqCallback(preq);
+	//erase first!
+	m_preqQueue.erase(m_preqQueue.begin());
+	//reschedule sending PREQ
+		NS_ASSERT(!m_preqTimer.IsRunning());
+	m_preqTimer = Simulator::Schedule(dot11sParameters::dot11MeshHWMPpreqMinInterval, &HwmpState::SendOnePreq, this);
+}
+
+void
+HwmpState::SendPrep(Mac48Address dst,
+		Mac48Address src,
+		Mac48Address retransmitter,
+		uint32_t initMetric,
+		uint32_t dsn,
+		uint32_t originatorDsn,
+		uint32_t lifetime)
+{
+	WifiPrepInformationElement prep;
+	prep.SetHopcount(0);
+	prep.SetTTL(m_maxTtl);
+	prep.SetDestinationAddress(dst);
+	prep.SetDestinationSeqNumber(dsn);
+	prep.SetLifetime(lifetime);
+	prep.SetMetric(0);
+	prep.SetOriginatorAddress(src);
+	prep.SetOriginatorSeqNumber(originatorDsn);
+	m_prepCallback(prep, retransmitter);
+}
+
+void
+HwmpState::SendOnePerr()
+{
+	if(m_myPerr.GetNumOfDest() == 0)
+		return;
+	m_perrCallback(m_myPerr, m_myPerrReceivers);
+	m_myPerr.ResetPerr();
+}
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-hwmp/hwmp-state.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,206 @@
+/* -*-  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 <map>
+#include "ns3/event-id.h"
+#include "ns3/ptr.h"
+#include "ns3/hwmp-rtable.h"
+#include "ns3/packet.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mesh-wifi-mac.h"
+#include "ns3/mesh-wifi-preq-information-element.h"
+#include "ns3/mesh-wifi-prep-information-element.h"
+#include "ns3/mesh-wifi-perr-information-element.h"
+#include "ns3/dot11s-parameters.h"
+namespace ns3 {
+	/**
+	 * \brief Handles HWMP state machine at each real interface
+	 * \details Implements the following:
+	 * 	1. Keep it's own DSN,
+	 * 	2. Keep PREQ and PREP timers adn send this frames in
+	 * 	accordance with HWMP-limitations
+	 * 	3. Deliver routing information to Hwmp main class
+	 * 	4. Notify about broken peers
+	 */
+	class HwmpState : public Object {
+		public:
+			static TypeId GetTypeId();
+			HwmpState();
+			~HwmpState();
+
+			/**
+			 * \brief Interface with HWMP - Hwmp can only
+			 * request address and collect routing
+			 * information
+			 */
+			void	SetRequestRouteCallback(
+					Callback<struct HwmpRtable::LookupResult, const Mac48Address&> cb);
+			void	SetRequestRootPathCallback(
+					Callback<struct HwmpRtable::LookupResult, uint32_t> cb);
+
+			enum InfoType {
+				INFO_PREQ,
+				INFO_PREP,
+				INFO_PERR,
+				INFO_PROACTIVE,
+				INFO_NEW_PEER,
+				INFO_FAILED_PEER
+			};
+			typedef struct RoutingInfo{
+				Mac48Address	me;
+				Mac48Address	destination;
+				Mac48Address	source;
+				Mac48Address	nextHop;
+				Mac48Address	prevHop;
+				uint32_t	outPort;
+				uint32_t	metric;
+				std::vector<Mac48Address>
+						failedDestinations;
+				uint32_t	dsn;
+				Time		lifetime;
+				enum InfoType	type;
+			} INFO;
+			void	SetRoutingInfoCallback(
+					Callback<void, INFO> cb
+					);
+			void	SetRetransmittersOfPerrCallback(
+					Callback<std::vector<Mac48Address>, std::vector<struct HwmpRtable::FailedDestination>, uint32_t> cb);
+			void	RequestDestination(Mac48Address dest);
+			void	SendPathError(std::vector<struct HwmpRtable::FailedDestination> destinations);
+			void	SetAssociatedIfaceId(uint32_t interface);
+			uint32_t
+				GetAssociatedIfaceId();
+			//Mac interaction:
+			void	SetMac(Ptr<MeshWifiMac> mac);
+			void	SetSendPreqCallback(
+					Callback<void, const WifiPreqInformationElement&> cb);
+			void	SetSendPrepCallback(
+					Callback<void, const WifiPrepInformationElement&> cb);
+			void	SetSendPerrCallback(
+					Callback<void, const WifiPerrInformationElement&, std::vector<Mac48Address> > cb);
+			void	ReceivePreq(WifiPreqInformationElement&, const Mac48Address& from, const uint32_t& metric);
+			void	ReceivePrep(WifiPrepInformationElement&, const Mac48Address& from, const uint32_t& metric);
+			void	ReceivePerr(WifiPerrInformationElement&, const Mac48Address& from);
+			void	PeerStatus(
+					const Mac48Address peerAddress,
+					const bool status,
+					const uint32_t metric
+					);
+			//Proactive mode routines:
+			bool	SetRoot();
+			void	UnSetRoot();
+			//external handling:
+			void	Disable();
+			void	Enable();
+			//DEBUG purpose:
+			Mac48Address GetAddress();
+		private:
+			static const uint32_t MAX_PREQ_ID = 0xffffffff;
+			static const uint32_t MAX_DSN = 0xffffffff;
+			//information about associated port:
+			Mac48Address	m_address;
+			//index when HWMP state is attached
+			uint32_t	m_ifIndex;
+			//timers for PREQ and PREP:
+			EventId		m_preqTimer;
+			void		SendOnePreq();
+			std::vector<WifiPreqInformationElement>
+					m_preqQueue;
+			//true means that we can add a destination to
+			//existing PREQ element
+			//False means that we must send 
+			EventId		m_prepTimer;
+			void		SendPrep(
+					Mac48Address	dst, //dst is PREQ's originator address
+					Mac48Address	src, //src is PREQ's destination address
+					Mac48Address	retransmitter,
+					uint32_t	initMetric,
+					uint32_t	dsn,/* taken form PREQ*/
+					uint32_t	originatorDsn, //taken from rtable or as m_myDsn ++;
+					uint32_t	lifetime	//taken from PREQ
+					);
+			std::vector<WifiPreqInformationElement>::iterator
+					m_myPreq;
+			//HWMP interaction callbacks:
+			Callback<void, INFO>
+					m_routingInfoCallback;
+			Callback<std::vector<Mac48Address>, std::vector<struct HwmpRtable::FailedDestination>, uint32_t>
+					m_retransmittersOfPerrCallback;
+			Callback<struct HwmpRtable::LookupResult, const Mac48Address&>
+					m_requestRouteCallback;
+			Callback<struct HwmpRtable::LookupResult, uint32_t>
+					m_requestRootPathCallback;
+			//Mac interaction callbacks:
+			Callback<void, const WifiPreqInformationElement&>
+					m_preqCallback;
+			Callback<void, const WifiPrepInformationElement&, const Mac48Address&>
+					m_prepCallback;
+			Callback<void, const WifiPerrInformationElement&, std::vector<Mac48Address> >
+					m_perrCallback;
+			//HwmpCounters:
+			uint32_t	m_preqId;
+			uint32_t	m_myDsn;
+			//Seqno and metric database
+			struct addrcmp
+			{
+				bool operator()(const Mac48Address addr1, Mac48Address addr2) const
+				{
+					uint8_t s1[6], s2[6];
+					addr1.CopyTo(s1);
+					addr2.CopyTo(s2);
+					for(int i = 0; i < 6; i ++)
+						if(s1[i] > s2[i])
+							return true;
+					return false;
+				}
+			};
+			std::map<Mac48Address, uint32_t, addrcmp>
+					m_dsnDatabase;
+			std::map<Mac48Address, uint32_t, addrcmp>
+					m_preqMetricDatabase;
+			//Disable/enable functionality
+			bool		m_disabled;
+			//Proactive PREQ mechanism:
+			EventId		m_proactivePreqTimer;
+			void		SendProactivePreq();
+			/**
+			 * \brief Two PERRs may not be sent closer to
+			 * each other than
+			 * dot11MeshHWMPperrMinInterval, so, each HWMP
+			 * state collects all unreachable destinations
+			 * and once in dot11MeshHWMPperrMinInterval
+			 * should send PERR, and PERR element should
+			 * be cleared
+			 */
+			WifiPerrInformationElement
+					m_myPerr;
+			std::vector<Mac48Address>
+					m_myPerrReceivers;
+			void		AddPerrReceiver(Mac48Address receiver);
+			EventId		m_perrTimer;
+			void		SendOnePerr();
+			//Configurable parameters:
+			uint8_t		m_maxTtl;
+	};
+} //namespace ns3
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-hwmp/hwmp.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,699 @@
+/* -*-  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 "ns3/hwmp.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+
+NS_LOG_COMPONENT_DEFINE ("Hwmp");
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Hwmp);
+NS_OBJECT_ENSURE_REGISTERED (HwmpTag);
+//Class HwmpTag:
+HwmpTag::HwmpTag()
+{
+}
+
+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 (void)
+{
+	static TypeId tid = TypeId ("ns3::HwmpTag")
+		.SetParent<Tag> ()
+		.AddConstructor<HwmpTag> ()
+		;
+	return tid;
+}
+
+TypeId
+HwmpTag::GetInstanceTypeId(void) const
+{
+	return GetTypeId();
+}
+
+uint32_t
+HwmpTag::GetSerializedSize(void) const
+{
+
+	return 6	//address
+		+1	//ttl
+		+4;	//metric
+}
+
+void
+HwmpTag::Serialize(TagBuffer i) const
+{
+	uint8_t address[6];
+	int j;
+	m_address.CopyTo(address);
+	i.WriteU8(m_ttl);
+	i.WriteU32(m_metric);
+	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();
+	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;
+}
+void
+HwmpTag::DecrementTtl()
+{
+	m_ttl --;
+}
+//Class HWMP:
+TypeId
+Hwmp::GetTypeId (void)
+{
+	static TypeId tid = TypeId ("ns3::Hwmp")
+		.SetParent<L2RoutingProtocol> ()
+                .AddConstructor<Hwmp>();
+	return tid;
+}
+Hwmp::Hwmp()
+{
+	m_maxTtl = 32;
+	m_broadcastPerr = false;
+	m_rtable = CreateObject<HwmpRtable> ();
+}
+
+Hwmp::~Hwmp()
+{
+}
+
+void
+Hwmp::DoDispose()
+{
+	for(std::map<Mac48Address, EventId, addrcmp>::iterator i = m_timeoutDatabase.begin(); i != m_timeoutDatabase.end(); i ++)
+		i->second.Cancel();
+	m_timeoutDatabase.clear();
+	m_seqnoDatabase.clear();
+	m_rtable = 0;
+
+	/**
+	 * clear routing queue:
+	 */
+	for(
+			std::map<Mac48Address, std::queue<struct QueuedPacket> >::iterator i =  m_rqueue.begin();
+			i != m_rqueue.end();
+			i++
+	   )
+	{
+		while(1)
+		{
+			if(i->second.empty())
+				break;
+			i->second.pop();
+		}
+	}
+	m_rqueue.clear();
+	/**
+	 * clear HWMP states
+	 */
+	for(unsigned int i = 0; i < m_hwmpStates.size(); i ++)
+		m_hwmpStates[i] = 0;
+	m_hwmpStates.clear();
+}
+
+bool
+Hwmp::RequestRoute(
+		uint32_t sourceIface,
+		const Mac48Address source,
+		const Mac48Address destination,
+		Ptr<Packet> packet,
+		uint16_t protocolType, //ethrnet 'Protocol' field
+		L2RoutingProtocol::RouteReplyCallback routeReply
+		)
+{
+	struct HwmpRtable::LookupResult result;
+	HwmpTag tag;
+	if(sourceIface == m_interface)
+	{
+		if(destination == Mac48Address::GetBroadcast())
+		{
+		//set seqno!
+		tag.SetSeqno(m_seqno++);
+		if(m_seqno == MAX_SEQNO)
+			m_seqno = 0;
+		}
+		tag.SetTtl(m_maxTtl);
+	}
+	else
+	{
+		NS_ASSERT(packet->FindFirstMatchingTag(tag));
+		//check seqno!
+		if(destination == Mac48Address::GetBroadcast())
+		{
+			std::map<Mac48Address, uint32_t, addrcmp>::iterator i = m_seqnoDatabase.find(source);
+			if(i == m_seqnoDatabase.end())
+				m_seqnoDatabase[source] = tag.GetSeqno();
+			else
+			{
+				if(i->second >= tag.GetSeqno())
+					return false;
+				m_seqnoDatabase[source] = tag.GetSeqno();
+			}
+		}
+	}
+	tag.SetAddress(Mac48Address::GetBroadcast());
+	if(tag.GetTtl() == 0)
+		return false;
+	tag.DecrementTtl();
+	if(destination == Mac48Address::GetBroadcast())
+	{
+		//add RA tag RA = broadcast
+		packet->RemoveAllTags();
+		packet->AddTag(tag);
+		routeReply(
+				true,
+				packet,
+				source,
+				destination,
+				protocolType,
+				HwmpRtable::PORT_ANY	
+			  );
+		return true;
+	}
+	result = m_rtable->LookupReactive(destination);
+	if (result.retransmitter == Mac48Address::GetBroadcast())
+	{
+		//no actual route exists, queue packet and start route
+		//discover procedure
+		if(sourceIface != m_interface)
+		{
+			//Start path error procedure:
+			NS_LOG_DEBUG("Must Send PERR");
+			std::vector<struct HwmpRtable::FailedDestination> destinations;
+			struct HwmpRtable::FailedDestination dst;
+			dst.seqnum = m_rtable->RequestSeqnum(destination);
+			dst.destination = destination;
+			destinations.push_back(dst);
+			StartPathErrorProcedure(destinations, result.ifIndex);
+		}
+		struct L2RoutingProtocol::QueuedPacket pkt;
+		packet->RemoveAllTags();
+		packet->AddTag(tag);
+		pkt.pkt = packet;
+		pkt.dst = destination;
+		pkt.src = source;
+		pkt.protocol = protocolType;
+		pkt.reply = routeReply;
+		pkt.inPort = sourceIface;
+		QueuePacket(pkt);
+		for(unsigned int i = 0; i< m_requestCallback.size(); i++)
+		{
+			if((m_modes[i] == REACTIVE) || (m_modes[i] == ROOT))
+			{
+				if(ShouldSendPreq(destination))
+					m_requestCallback[i](destination);
+			}
+			else
+			{
+				NS_ASSERT(false);
+				//PROACTIVE mode
+				//lookup a default route
+				result = m_rtable->LookupProactive(m_hwmpStates[i]->GetAssociatedIfaceId());
+				if(result.retransmitter == Mac48Address::GetBroadcast())
+				{
+					m_rtable->DeleteProactivePath(m_hwmpStates[i]->GetAssociatedIfaceId());
+					m_modes[i] = REACTIVE;
+					if(ShouldSendPreq(destination))
+						m_requestCallback[i](destination);
+					continue;
+				}
+				tag.SetAddress(result.retransmitter);
+				packet->RemoveAllTags();
+				packet->AddTag(tag);
+				routeReply(
+					true,
+					packet,
+					source,
+					destination,
+					protocolType,
+					result.ifIndex
+				  );
+			}
+		}
+		for(unsigned int i = 0; i< m_requestCallback.size(); i++)
+		{
+			m_requestCallback[i](Mac48Address("00:00:00:00:00:19"));
+
+		}
+	}
+	else
+	{
+		tag.SetAddress(result.retransmitter);
+		packet->RemoveAllTags();
+		packet->AddTag(tag);
+		routeReply(
+				true,
+				packet,
+				source,
+				destination,
+				protocolType,
+				result.ifIndex
+			  );
+	}
+	return true;
+}
+bool
+Hwmp::AttachPorts(std::vector<Ptr<NetDevice> > ports)
+{
+	for(std::vector<Ptr<NetDevice> >::iterator i = ports.begin(); i != ports.end(); i++)
+	{
+		//Checking netdevice:
+		const WifiNetDevice * wifiNetDev = dynamic_cast<const WifiNetDevice *> (PeekPointer (*i));
+		if(wifiNetDev == NULL)
+			return false;
+		MeshWifiMac * meshWifiMac = dynamic_cast<MeshWifiMac *> (PeekPointer (wifiNetDev->GetMac()));
+		if(meshWifiMac == NULL)
+			return false;
+		//Adding HWMP-state
+		Ptr<HwmpState> hwmpState = CreateObject<HwmpState> ();
+		hwmpState->SetRoutingInfoCallback(MakeCallback(&Hwmp::ObtainRoutingInformation, this));
+		hwmpState->SetMac(meshWifiMac);
+		hwmpState->SetRequestRouteCallback(MakeCallback(&Hwmp::RequestRouteForAddress, this));
+		hwmpState->SetRequestRootPathCallback(MakeCallback(&Hwmp::RequestRootPathForPort, this));
+		hwmpState->SetAssociatedIfaceId(wifiNetDev->GetIfIndex());
+		hwmpState->SetRetransmittersOfPerrCallback(MakeCallback(&Hwmp::GetRetransmittersForFailedDestinations,this));
+		m_hwmpStates.push_back(hwmpState);
+		m_requestCallback.push_back(MakeCallback(&HwmpState::RequestDestination, hwmpState));
+		m_pathErrorCallback.push_back(MakeCallback(&HwmpState::SendPathError, hwmpState));
+		//Default mode is reactive, default state is enabled
+		enum DeviceState state = ENABLED;
+		enum DeviceMode  mode = REACTIVE;
+		m_states.push_back(state);
+		m_modes.push_back(mode);
+	}
+	return true;
+}
+
+void
+Hwmp::SetIfIndex(uint32_t interface)
+{
+	m_interface = interface;
+}
+
+void
+Hwmp::DisablePort(uint32_t port)
+{
+	int position = 0;
+	for(std::vector<Ptr<HwmpState> >::iterator i = m_hwmpStates.begin(); i!= m_hwmpStates.end(); i++)
+	{
+		if((*i)->GetAssociatedIfaceId() == port)
+		{
+			m_states[position] = DISABLED;
+			m_hwmpStates[position]->Disable();
+			return;
+		}
+		position ++;
+	}
+}
+
+void
+Hwmp::EnablePort(uint32_t port)
+{
+	int position = 0;
+	for(std::vector<Ptr<HwmpState> >::iterator i = m_hwmpStates.begin(); i!= m_hwmpStates.end(); i++)
+	{
+		if((*i)->GetAssociatedIfaceId() == port)
+		{
+			m_states[position] = ENABLED;
+			m_hwmpStates[position]->Enable();
+			return;
+		}
+		position ++;
+	}
+}
+
+void
+Hwmp::SetRoot(uint32_t port)
+{
+	int position = 0;
+	for(std::vector<Ptr<HwmpState> >::iterator i = m_hwmpStates.begin(); i!= m_hwmpStates.end(); i++)
+	{
+		if(((*i)->GetAssociatedIfaceId() == port)||(port == HwmpRtable::PORT_ANY))
+		{
+			if(m_hwmpStates[position]->SetRoot())
+			{
+				m_modes[position] = ROOT;
+				NS_LOG_DEBUG("I am proactive");
+			}
+		}
+		position ++;
+	}
+}
+void
+Hwmp::SetProactive(uint32_t port)
+{
+	int position = 0;
+	for(std::vector<Ptr<HwmpState> >::iterator i = m_hwmpStates.begin(); i!= m_hwmpStates.end(); i++)
+	{
+		if((*i)->GetAssociatedIfaceId() == port)
+		{
+			m_modes[position] = PROACTIVE;
+			return;
+		}
+		position ++;
+	}
+}
+bool
+Hwmp::IsRoot(uint32_t port)
+{
+	int position = 0;
+	for(std::vector<Ptr<HwmpState> >::iterator i = m_hwmpStates.begin(); i!= m_hwmpStates.end(); i++)
+	{
+		if((*i)->GetAssociatedIfaceId() == port)
+			if(m_modes[position] == ROOT)
+				return true;
+		position ++;
+	}
+	return false;
+}
+void
+Hwmp::UnSetRoot(uint32_t port)
+{
+	int position = 0;
+	for(std::vector<Ptr<HwmpState> >::iterator i = m_hwmpStates.begin(); i!= m_hwmpStates.end(); i++)
+	{
+		if(((*i)->GetAssociatedIfaceId() == port)||(port == HwmpRtable::PORT_ANY))
+		{
+			m_modes[position] = REACTIVE;
+			m_hwmpStates[position]->UnSetRoot();
+		}
+		position ++;
+	}
+}
+
+void
+Hwmp::ObtainRoutingInformation(
+		HwmpState::INFO info
+				)
+{
+	switch(info.type)
+	{
+	case HwmpState::INFO_PREP:
+		if(info.me != info.source)
+		{
+			m_rtable->AddPrecursor(info.source, info.outPort, info.nextHop);
+			m_rtable->AddPrecursor(info.destination, info.outPort, info.prevHop);
+			NS_LOG_DEBUG("path to "<<info.source<<" precursor is "<<info.nextHop);
+			NS_LOG_DEBUG("path to "<<info.destination<<" precursor is "<<info.prevHop);
+		}
+	case HwmpState::INFO_PREQ:
+		m_rtable->AddReactivePath(
+				info.destination,
+				info.nextHop,
+				info.outPort,
+				info.metric,
+				info.lifetime,
+				info.dsn);
+		SendAllPossiblePackets(info.destination);
+		break;
+	case HwmpState::INFO_PERR:
+		//delete first subentry
+	case HwmpState::INFO_PROACTIVE:
+		//add information to the root MP.
+			m_rtable->AddProactivePath(
+			info.metric,
+			info.destination,
+			info.nextHop,
+			info.outPort,
+			info.lifetime,
+			info.dsn);
+			//Set mode as PROACTIVE:
+			SetProactive(info.outPort);
+		break;
+	case HwmpState::INFO_NEW_PEER:
+#if 0
+			m_rtable->AddReactivePath(
+				info.destination,
+				info.nextHop,
+				info.outPort,
+				info.metric,
+				Seconds(0),
+				0);
+#endif
+		break;
+	case HwmpState::INFO_FAILED_PEER:
+		/**
+		 * Conditions for generating PERR
+		 */
+		{
+			NS_LOG_DEBUG("Failed peer"<<info.destination);
+			std::vector<struct HwmpRtable::FailedDestination> failedDestinations = 
+				m_rtable->GetUnreachableDestinations(info.destination, info.outPort);
+			/**
+			 * Entry about peer does not contain seqnum
+			 */
+			struct HwmpRtable::FailedDestination peer;
+			peer.destination = info.destination;
+			peer.seqnum = 0;
+			failedDestinations.push_back(peer);
+			StartPathErrorProcedure(failedDestinations, info.outPort);
+		}
+		break;
+	default:
+		return;
+	}
+}
+
+struct HwmpRtable::LookupResult
+Hwmp::RequestRouteForAddress(const Mac48Address& dst)
+{
+	return m_rtable->LookupReactive(dst);
+}
+
+struct	HwmpRtable::LookupResult
+Hwmp::RequestRootPathForPort(uint32_t port)
+{
+	return m_rtable->LookupProactive(port);
+}
+
+void
+Hwmp::StartPathErrorProcedure(std::vector<struct HwmpRtable::FailedDestination> destinations, uint32_t port)
+{
+	NS_LOG_DEBUG("START PERR");
+	for(unsigned int i  = 0; i < m_hwmpStates.size(); i++)
+		if(m_hwmpStates[i]->GetAssociatedIfaceId() == port)
+			m_pathErrorCallback[i](destinations);
+}
+std::vector<Mac48Address>
+Hwmp::GetRetransmittersForFailedDestinations(std::vector<struct HwmpRtable::FailedDestination> failedDest, uint32_t port)
+{
+	std::vector<Mac48Address> retransmitters;
+	if(m_broadcastPerr)
+		retransmitters.push_back(Mac48Address::GetBroadcast());
+	else
+		for(unsigned int i = 0; i< failedDest.size(); i ++)
+		{
+			std::vector<Mac48Address> precursors = 
+				m_rtable->GetPrecursors(failedDest[i].destination, port);
+			for(unsigned int j = 0; j < precursors.size(); j++)
+			{
+				for(unsigned int k = 0; k < retransmitters.size(); k ++)
+					if(retransmitters[k] == precursors[j])
+						break;
+				retransmitters.push_back(precursors[j]);
+			}
+		}
+	for(unsigned int i = 0; i < failedDest.size(); i ++)
+	{
+		m_rtable->DeleteReactivePath(failedDest[i].destination, port);
+		m_rtable->DeleteProactivePath(failedDest[i].destination, port);
+	}
+	return retransmitters;
+}
+void
+Hwmp::SetMaxQueueSize(int maxPacketsPerDestination)
+{
+	m_maxQueueSize = maxPacketsPerDestination;
+}
+
+bool
+Hwmp::QueuePacket(struct L2RoutingProtocol::QueuedPacket packet)
+{
+	if((int)m_rqueue[packet.dst].size() > m_maxQueueSize)
+		return false;
+	m_rqueue[packet.dst].push(packet);
+	return true;
+}
+
+struct L2RoutingProtocol::QueuedPacket
+Hwmp::DequeuePacket(Mac48Address dst)
+{
+	struct L2RoutingProtocol::QueuedPacket retval;
+	retval.pkt = NULL;
+	//Ptr<Packet> in this structure is NULL when queue is empty
+	std::map<Mac48Address, std::queue<struct QueuedPacket>, addrcmp>:: iterator i = m_rqueue.find(dst);
+	if(i == m_rqueue.end())
+		return retval;
+	if((int)m_rqueue[dst].size() == 0)
+		return retval;
+	if((int)i->second.size() == 0)
+	{
+		m_rqueue.erase(i);
+		return retval;
+	}
+	retval = m_rqueue[dst].front();
+	m_rqueue[dst].pop();
+	return retval;
+}
+
+void
+Hwmp::SendAllPossiblePackets(Mac48Address dst)
+{
+	struct HwmpRtable::LookupResult result = m_rtable->LookupReactive(dst);
+	struct L2RoutingProtocol::QueuedPacket packet;
+		while(1)
+		       
+		{
+			packet = DequeuePacket(dst);
+			if(packet.pkt == NULL)
+			return;
+			//set RA tag for retransmitter:
+			HwmpTag tag;
+			NS_ASSERT(packet.pkt->FindFirstMatchingTag(tag));
+			tag.SetAddress(result.retransmitter);
+			NS_ASSERT(result.retransmitter!=Mac48Address::GetBroadcast());
+			packet.pkt->RemoveAllTags();
+			packet.pkt->AddTag(tag);
+			packet.reply(true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
+		}
+}
+
+bool
+Hwmp::ShouldSendPreq(Mac48Address dst)
+{
+	std::map<Mac48Address, EventId, addrcmp>::iterator i = m_timeoutDatabase.find(dst);
+	if(i == m_timeoutDatabase.end())
+	{
+		m_timeoutDatabase[dst] = Simulator::Schedule(
+				MilliSeconds(2*(dot11sParameters::dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds())),
+				&Hwmp::RetryPathDiscovery, this, dst, 0);
+		return true;
+	}
+	return false;
+}
+void
+Hwmp::RetryPathDiscovery(Mac48Address dst, uint8_t numOfRetry)
+{
+	struct HwmpRtable::LookupResult result = m_rtable->LookupReactive(dst);
+	if(result.retransmitter != Mac48Address::GetBroadcast())
+	{
+		std::map<Mac48Address, EventId, addrcmp>::iterator i = m_timeoutDatabase.find(dst);
+		NS_ASSERT(i!=  m_timeoutDatabase.end());
+		m_timeoutDatabase.erase(i);
+		return;
+	}
+	numOfRetry++;
+	if(numOfRetry > dot11sParameters::dot11MeshHWMPmaxPREQretries)
+	{
+		struct L2RoutingProtocol::QueuedPacket packet;
+		//purge queue and delete entry from retryDatabase
+		while(1)
+		{
+			packet = DequeuePacket(dst);
+			if(packet.pkt == NULL)
+				break;
+			packet.reply(false, packet.pkt, packet.src, packet.dst, packet.protocol, HwmpRtable::MAX_METRIC);
+		}
+		std::map<Mac48Address, EventId, addrcmp>::iterator i = m_timeoutDatabase.find(dst);
+		NS_ASSERT(i!=  m_timeoutDatabase.end());
+		m_timeoutDatabase.erase(i);
+		return;
+	}
+	for(unsigned int i = 0; i< m_requestCallback.size(); i++)
+		if((m_modes[i] == REACTIVE) || (m_modes[i] == ROOT))
+				m_requestCallback[i](dst);
+	m_timeoutDatabase[dst] = Simulator::Schedule(
+			MilliSeconds(2*(dot11sParameters::dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds())),
+			&Hwmp::RetryPathDiscovery, this, dst, numOfRetry);
+}
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-hwmp/hwmp.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,303 @@
+/* -*-  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 HWMP_H
+#define HWMP_H
+#include <map>
+#include <queue>
+#include "ns3/tag.h"
+#include "ns3/object.h"
+#include "ns3/mac48-address.h"
+#include "ns3/l2-routing-protocol.h"
+#include "ns3/packet.h"
+#include "ns3/ptr.h"
+#include "hwmp-state.h"
+namespace ns3 {
+	class HwmpState;
+	/**
+	 * \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 (void);
+			virtual TypeId		GetInstanceTypeId (void) const;
+			virtual uint32_t	GetSerializedSize (void) 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;
+	};
+	class Hwmp : public L2RoutingProtocol
+	{
+		public:
+			static TypeId GetTypeId();
+			Hwmp();
+			~Hwmp();
+			void	DoDispose();
+			//intheritedfrom L2RoutingProtocol
+			/**
+			 * \brief L2Routing protocol base class metod
+			 *
+			 * \details Route resolving procedure consits
+			 * of the following steps:
+			 * 1. Find reactive route and send a packet.
+			 * 2. Find all ports which are operate in
+			 * 'Proactive' mode and find a proper default
+			 * routes. and send packet to all proactive
+			 * 'ports'.
+			 * 3. If there are ports which are operate in
+			 * reactive mode - queue packet and start
+			 * route reactive path discovery
+			 *
+			 * \bug Now packet is sent to the 'best root'
+			 * rather than to the best root at each port
+			 */
+			bool	RequestRoute(
+					uint32_t		sourceIface,
+					const Mac48Address	source,
+					const Mac48Address	destination,
+					Ptr<Packet>		packet,
+					uint16_t		protocolType,
+					L2RoutingProtocol::RouteReplyCallback
+					routeReply
+					);
+			bool	AttachPorts(std::vector<Ptr<NetDevice> >);
+			void	SetIfIndex(uint32_t interface);
+			/**
+			 * \brief Disables port by index.
+			 * \details Needed for external modules like
+			 * clusterization.
+			 */
+			void	DisablePort(uint32_t port);
+			/**
+			 * \brief enables port
+			 */
+			void	EnablePort(uint32_t port);
+			/**
+			 * \brief Setting proative mode.
+			 * \details To enable proactive mode you must
+			 * set a root node. Choosing the route is made
+			 * in accordance with the following: 
+			 * 	1. Find 'reactive' route. If route is
+			 * 	found - send a packet using this
+			 * 	information
+			 * 	2. If there is no reactive route -
+			 * 	find proactive or 'default' route.
+			 * \attention Comparsion between proactive and
+			 * reactive routes is incorrect, because we
+			 * have metric to root MP in te first case and
+			 * metric to the destination in the second
+			 * case.
+			 * \param port is the port where proactive
+			 * mode should be activated
+			 */
+			void	SetRoot(uint32_t port);
+			/**
+			 * \brief Disable root functionality at a
+			 * given port
+			 */
+			void	UnSetRoot(uint32_t port);
+			/**
+			 * \brief HwmpState retrns to Hwmp class all
+			 * routing information obtained from all HWMP
+			 * action frames
+			 */
+			void	ObtainRoutingInformation(
+					HwmpState::INFO info
+					);
+			/**
+			 * \brief Hwmp state noyifyes that neighbour
+			 * is dissapeared. Hwmp state knows about peer
+			 * failure from MAC
+			 */
+			void	PeerFailure(Mac48Address peerAddress);
+			void	SetMaxTtl(uint8_t ttl);
+			uint8_t
+				GetMaxTtl();
+		private:
+			static const uint32_t MAX_SEQNO = 0xffffffff;
+			//candidate queue is implemented inside the
+			//protocol:
+			void		SetMaxQueueSize(int maxPacketsPerDestination);
+			int		m_maxQueueSize;
+			bool		QueuePacket(struct L2RoutingProtocol::QueuedPacket packet);
+			struct		L2RoutingProtocol::QueuedPacket
+					DequeuePacket(Mac48Address dst);
+			void		SendAllPossiblePackets(Mac48Address dst);
+			struct addrcmp
+			{
+				bool operator()(const Mac48Address addr1, Mac48Address addr2) const
+				{
+					uint8_t s1[6], s2[6];
+					addr1.CopyTo(s1);
+					addr2.CopyTo(s2);
+					for(int i = 0; i < 6; i ++)
+						if(s1[i] > s2[i])
+							return true;
+					return false;
+				}
+			};
+			std::map<Mac48Address, std::queue<struct QueuedPacket> > 
+					m_rqueue;
+			//devices and HWMP states:
+			enum DeviceState {
+				ENABLED,
+				DISABLED
+			};
+			enum DeviceMode {
+				REACTIVE,
+				PROACTIVE,
+				ROOT
+			};
+			std::vector<enum DeviceState>
+					m_states;
+			std::vector<enum DeviceMode>
+					m_modes;
+			std::vector<Ptr<HwmpState> >
+					m_hwmpStates;
+			//Routing table:
+			Ptr<HwmpRtable>
+					m_rtable;
+			//Proactive routines:
+			/**
+			 * \brief Set port state as proactive.
+			 * \details mode is supposed to be proactive
+			 * when proatcive PREQ with a valid
+			 * information was received.
+			 */
+			void		SetProactive(uint32_t port);
+			/**
+			 * \brief Checks if the port is root, if true
+			 * - no default routes must be used at this
+			 * port
+			 */
+			bool		IsRoot(uint32_t port);
+			/**
+			 * \brief Interaction with HwmpState class -
+			 * request for starting routing discover
+			 * procedure (reactive route discovery!)
+			 * \param Mac48Address is destination to be
+			 * resolved
+			 */
+			std::vector< Callback<void, Mac48Address> >
+					m_requestCallback;
+			/**
+			 * \brief Callback that shall be executed when
+			 * need to send Path error
+			 * \param std::vector<Mac48Address> is the
+			 * list of unreachable destinations
+			 * \param std::vector<Mac48Address> is
+			 * receivers of PERR
+			 */
+			std::vector<Callback<void,std::vector<struct HwmpRtable::FailedDestination> > >
+					m_pathErrorCallback;
+			void	StartPathErrorProcedure(
+					std::vector<struct HwmpRtable::FailedDestination> destinations,
+					uint32_t port);
+			/**
+			 * \brief HwmpState need to know where to
+			 * retransmit PERR, only HWMP knows how to
+			 * retransmit it (broadcast/unicast) and only
+			 * HWMP has accessto routing table
+			 */
+			std::vector<Mac48Address>
+					GetRetransmittersForFailedDestinations(
+							std::vector<struct HwmpRtable::FailedDestination> failedDest,
+							uint32_t port);
+			/**
+			 * \brief Needed by HwmpState to find routes in case
+			 * of intermediate reply and choosing the
+			 * better route
+			 * 
+			 */
+			struct	HwmpRtable::LookupResult
+					RequestRouteForAddress(const Mac48Address& destination);
+			struct	HwmpRtable::LookupResult
+					RequestRootPathForPort(uint32_t port);
+
+			/**
+			 * \brief interface which is the HWMP attached to
+			 * (Virtual netdevice)
+			 */
+			uint32_t	m_interface;
+			/**
+			 * \attention mesh seqno is processed at HWMP
+			 */
+			uint32_t	m_seqno;
+			std::map<Mac48Address, uint32_t, addrcmp>
+					m_seqnoDatabase;
+			//Timers:
+			/**
+			 * /brief checks when last preq was initiated, returns
+			 * false when retry has not expired
+			 */
+			bool		ShouldSendPreq(Mac48Address dst);
+			/**
+			 * \brief Generates PREQ retry when route is
+			 * still unresolved after first PREQ
+			 * If number of retries greater than
+			 * dot11sParameters::dot11MeshHWMPmaxPREQretries,
+			 * we return all packets to upper layers
+			 */
+			void		RetryPathDiscovery(Mac48Address dst, uint8_t numOfRetry);
+			/**
+			 * Keeps PREQ retry timers for every
+			 * destination
+			 */
+			std::map<Mac48Address, EventId, addrcmp>
+					m_timeoutDatabase;
+			/**
+			 * Configurable parameters:
+			 */
+			uint8_t		m_maxTtl;
+			bool		m_broadcastPerr;
+	};
+} //namespace ns3
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-hwmp/waf	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../../waf "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-hwmp/wscript	Sat Feb 28 14:21:05 2009 +0300
@@ -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('l2-routing-hwmp', ['node', 'l2-routing-main'])
+    obj.source = [
+	'hwmp-rtable.cc',
+	'hwmp-state.cc',
+	'hwmp.cc',
+        ]
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'l2-routing-hwmp'
+    headers.source = [
+	'hwmp-rtable.h',
+	'hwmp-state.h',
+	'hwmp.h',
+        ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-main/l2-routing-net-device.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,355 @@
+/* -*-  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/node.h"
+#include "ns3/channel.h"
+#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/boolean.h"
+#include "ns3/simulator.h"
+#include "ns3/l2-routing-net-device.h"
+
+NS_LOG_COMPONENT_DEFINE ("L2RoutingNetDevice");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (L2RoutingNetDevice);
+
+
+TypeId
+L2RoutingNetDevice::GetTypeId (void)
+{
+	static TypeId tid = TypeId ("ns3::L2RoutingNetDevice")
+		.SetParent<NetDevice> ()
+		.AddConstructor<L2RoutingNetDevice> ()
+		;
+	return tid;
+}
+
+
+L2RoutingNetDevice::L2RoutingNetDevice ()
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	m_channel = CreateObject<BridgeChannel> ();
+}
+
+L2RoutingNetDevice::~L2RoutingNetDevice()
+{
+	NS_LOG_FUNCTION_NOARGS ();
+}
+
+	void
+L2RoutingNetDevice::DoDispose ()
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin (); iter != m_ports.end (); iter++)
+		*iter = 0;
+	m_ports.clear ();
+	m_node = 0;
+	NetDevice::DoDispose ();
+
+}
+
+	void
+L2RoutingNetDevice::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);
+	if (!m_promiscRxCallback.IsNull ())
+		m_promiscRxCallback (this, packet, protocol, src, dst, packetType);
+	switch (packetType)
+	{
+		case PACKET_HOST:
+			if (dst48 == m_address)
+				m_rxCallback (this, packet, protocol, src);
+			break;
+		case PACKET_BROADCAST:
+		case PACKET_MULTICAST:
+			m_rxCallback (this, packet, protocol, src);
+		case PACKET_OTHERHOST:
+			Forward (incomingPort, packet->Copy(), protocol, src48, dst48);
+			break;
+	}
+
+}
+
+void
+L2RoutingNetDevice::Forward (Ptr<NetDevice> inport, Ptr<Packet> packet,
+		uint16_t protocol, const Mac48Address src, const Mac48Address dst)
+{
+	//pass through routing protocol
+	m_requestRoute(inport->GetIfIndex(), src, dst, packet, protocol, m_myResponse);
+}
+
+uint32_t
+L2RoutingNetDevice::GetNPorts (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return m_ports.size ();
+}
+
+Ptr<NetDevice>
+L2RoutingNetDevice::GetPort (uint32_t n) const
+{
+	NS_ASSERT(m_ports.size () > n);
+	return m_ports[n];
+}
+
+void
+L2RoutingNetDevice::AddPort (Ptr<NetDevice> routingPort)
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	NS_ASSERT (routingPort != this);
+	if (!Mac48Address::IsMatchingType (routingPort->GetAddress ()))
+		NS_FATAL_ERROR ("Device does not support eui 48 addresses: cannot be added to bridge.");
+	if (!routingPort->SupportsSendFrom ())
+		NS_FATAL_ERROR ("Device does not support SendFrom: cannot be added to bridge.");
+	m_address = Mac48Address::ConvertFrom (routingPort->GetAddress ());
+	NS_LOG_DEBUG ("RegisterProtocolHandler for " << routingPort->GetName ());
+	m_node->RegisterProtocolHandler (MakeCallback (&L2RoutingNetDevice::ReceiveFromDevice, this),
+			0, routingPort, true);
+	m_ports.push_back (routingPort);
+	m_channel->AddChannel (routingPort->GetChannel ());
+}
+
+	void
+L2RoutingNetDevice::SetName(const std::string name)
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	m_name = name;
+}
+
+std::string
+L2RoutingNetDevice::GetName(void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return m_name;
+}
+
+	void
+L2RoutingNetDevice::SetIfIndex(const uint32_t index)
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	m_ifIndex = index;
+}
+
+uint32_t
+L2RoutingNetDevice::GetIfIndex(void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return m_ifIndex;
+}
+
+Ptr<Channel>
+L2RoutingNetDevice::GetChannel (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return m_channel;
+}
+
+Address
+L2RoutingNetDevice::GetAddress (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return m_address;
+}
+
+	bool
+L2RoutingNetDevice::SetMtu (const uint16_t mtu)
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	m_mtu = mtu;
+	return true;
+}
+
+uint16_t
+L2RoutingNetDevice::GetMtu (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return 1500;
+}
+
+
+bool
+L2RoutingNetDevice::IsLinkUp (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return true;
+}
+
+
+	void
+L2RoutingNetDevice::SetLinkChangeCallback (Callback<void> callback)
+{}
+
+bool
+L2RoutingNetDevice::IsBroadcast (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return true;
+}
+
+
+Address
+L2RoutingNetDevice::GetBroadcast (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+
+bool
+L2RoutingNetDevice::IsMulticast (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return true;
+}
+
+Address
+L2RoutingNetDevice::GetMulticast (Ipv4Address multicastGroup) const
+{
+	NS_LOG_FUNCTION (this << multicastGroup);
+	Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
+	return multicast;
+}
+
+
+bool
+L2RoutingNetDevice::IsPointToPoint (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return false;
+}
+
+bool
+L2RoutingNetDevice::IsBridge (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return false;
+}
+
+
+bool
+L2RoutingNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+
+	const Mac48Address dst48 = Mac48Address::ConvertFrom (dest);
+	return m_requestRoute(m_ifIndex, m_address, dst48, packet, protocolNumber, m_myResponse);
+}
+
+bool
+L2RoutingNetDevice::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_requestRoute(m_ifIndex, src48, dst48, packet, protocolNumber, m_myResponse);
+}
+
+
+Ptr<Node>
+L2RoutingNetDevice::GetNode (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return m_node;
+}
+
+
+	void
+L2RoutingNetDevice::SetNode (Ptr<Node> node)
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	m_node = node;
+}
+
+
+bool
+L2RoutingNetDevice::NeedsArp (void) const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return true;
+}
+
+
+	void
+L2RoutingNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	m_rxCallback = cb;
+}
+
+	void
+L2RoutingNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	m_promiscRxCallback = cb;
+}
+
+bool
+L2RoutingNetDevice::SupportsSendFrom () const
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	return true;
+}
+
+Address
+L2RoutingNetDevice::GetMulticast (Ipv6Address addr) const
+{
+	NS_LOG_FUNCTION (this << addr);
+	return Mac48Address::GetMulticast (addr);
+}
+//L2RouitingSpecific methods:
+
+bool
+L2RoutingNetDevice::AttachProtocol(Ptr<L2RoutingProtocol> protocol)
+{
+	m_requestRoute = MakeCallback(&L2RoutingProtocol::RequestRoute, protocol);
+	m_myResponse = MakeCallback(&L2RoutingNetDevice::ProtocolResponse, this);
+	protocol->SetIfIndex(m_ifIndex);
+	return protocol->AttachPorts(m_ports);
+}
+
+void
+L2RoutingNetDevice::ProtocolResponse(
+		bool success,
+		Ptr<Packet> packet,
+		Mac48Address src,
+		Mac48Address dst,
+		uint16_t protocol,
+		uint32_t outPort
+		)
+{
+	if(!success)
+	{
+		NS_LOG_UNCOND("Resolve failed");
+		//TODO: SendError callback
+		return;
+	}
+	//just do sendFrom!
+	if(outPort!=0xffffffff)
+		GetPort(outPort)->SendFrom(packet, src, dst, protocol);
+	else
+		for(std::vector<Ptr<NetDevice> >::iterator i = m_ports.begin(); i!= m_ports.end(); i++)
+			(*i) -> SendFrom(packet, src, dst, protocol);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-main/l2-routing-net-device.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,167 @@
+/* -*-  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 L2ROUTING_NET_DEVICE_H
+#define L2ROUTING_NET_DEVICE_H
+
+#include "ns3/net-device.h"
+#include "ns3/mac48-address.h"
+#include "ns3/nstime.h"
+#include "ns3/bridge-net-device.h"
+#include "ns3/bridge-channel.h"
+#include "ns3/l2-routing-protocol.h"
+
+namespace ns3 {
+	class Node;
+	/**
+	 * \ingroup devices
+	 * \defgroup L2RoutingNetDevice L2routingNetDevice
+	 */
+	/**
+	 * \ingroup L2RoutingNetDevice
+	 * \brief a virtual net device that may forward packets
+	 * between real network devices using routing protocols of
+	 * MAC-layer
+	 * \details This is a virtual netdevice, which aggreagates
+	 * real netdevices and uses interface of L2RoutingProtocol to
+	 * forward packets
+	 * \attention The idea of L2RoutingNetDevice is similar to
+	 * BridgeNetDevice, but the packets, which going through
+	 * L2RoutingNetDevice may be changed (because routing protocol
+	 * may require its own headers or tags). 
+	 */
+	class L2RoutingNetDevice : public NetDevice
+	{
+		public:
+			static TypeId GetTypeId (void);
+			L2RoutingNetDevice ();
+			virtual ~L2RoutingNetDevice ();
+			/**
+			 * \brief Attaches a 'port' to a virtual
+			 * L2RoutingNetDevice, and this port is handled
+			 * by L2RoutingProtocol.
+			 * \attention Like in a bridge,
+			 * L2RoutingNetDevice's ports must not have IP
+			 * addresses, and only L2RoutingNetDevice
+			 * itself may have an IP address.
+			 *
+			 * \attention L2RoutingNetDevice may be a port
+			 * of BridgeNetDevice.
+			 */
+			void AddPort (Ptr<NetDevice> port);
+			/**
+			 * \returns number of ports attached to
+			 * L2RoutingNetDevice
+			 */
+			uint32_t GetNPorts (void) const;
+			/**
+			 * \returns a pointer to netdevice
+			 * \param n is device ID to be returned
+			 */
+			Ptr<NetDevice> GetPort (uint32_t n) const;
+			//inherited from netdevice:
+			virtual void SetName(const std::string name);
+			virtual std::string GetName(void) const;
+			virtual void SetIfIndex(const uint32_t index);
+			virtual uint32_t GetIfIndex(void) const;
+			virtual Ptr<Channel> GetChannel (void) const;
+			virtual Address GetAddress (void) const;
+			virtual bool SetMtu (const uint16_t mtu);
+			virtual uint16_t GetMtu (void) const;
+			virtual bool IsLinkUp (void) const;
+			virtual void SetLinkChangeCallback (Callback<void> callback);
+			virtual bool IsBroadcast (void) const;
+			virtual Address GetBroadcast (void) const;
+			virtual bool IsMulticast (void) const;
+			virtual Address GetMulticast (Ipv4Address multicastGroup) const;
+			virtual bool IsPointToPoint (void) const;
+			virtual bool IsBridge (void) 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 (void) const;
+			virtual void SetNode (Ptr<Node> node);
+			virtual bool NeedsArp (void) 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 (void);
+			/**
+			 * \brief Attaches protocol to a given virtual
+			 * device
+			 * \returns true if success
+			 */
+			virtual bool AttachProtocol(Ptr<L2RoutingProtocol> protocol);
+		protected:
+			/**
+			 * \brief This is similar to BridgeNetDevice
+			 * method
+			 */
+			void ReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
+					Address const &source, Address const &destination, PacketType packetType);
+			/**
+			 * \brief This is similar to BridgeNetDevice
+			 * method
+			 */
+			void Forward (Ptr<NetDevice> incomingPort, Ptr<Packet> packet,
+					uint16_t protocol, const Mac48Address src, const Mac48Address dst);
+			/**
+			 * \brief This is a function, which should be
+			 * passed to L2RoutingProtocol as response
+			 * callback (see L2RoutingProtocol).
+			 */
+			virtual void ProtocolResponse(
+					bool success,
+					Ptr<Packet>,
+					Mac48Address src,
+					Mac48Address dst,
+					uint16_t protocol,
+					uint32_t outPort
+					);
+		private:
+			NetDevice::ReceiveCallback
+					m_rxCallback;
+			NetDevice::PromiscReceiveCallback
+					m_promiscRxCallback;
+			Mac48Address	m_address;
+			Ptr<Node>	m_node;
+			std::string	m_name;
+			std::vector< Ptr<NetDevice> >
+					m_ports;
+			uint32_t	m_ifIndex;
+			uint16_t	m_mtu;
+			Ptr<BridgeChannel>
+					m_channel;
+			Callback<
+				bool,
+				uint32_t,
+				Mac48Address,
+				Mac48Address,
+				Ptr<Packet>,
+				uint16_t,
+				L2RoutingProtocol::RouteReplyCallback>
+					m_requestRoute;
+			//What we give to L2Routing
+			L2RoutingProtocol::RouteReplyCallback
+					m_myResponse;
+	};
+} //namespace ns3
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-main/waf	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../../waf "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/l2-routing/l2-routing-main/wscript	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,12 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    obj = bld.create_ns3_module('l2-routing-main', ['node', 'bridge'])
+    obj.source = [
+	'l2-routing-net-device.cc',
+        ]
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'l2-routing-main'
+    headers.source = [
+	'l2-routing-net-device.h',
+        ]
--- a/src/devices/wifi/dca-txop.h	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/devices/wifi/dca-txop.h	Sat Feb 28 14:21:05 2009 +0300
@@ -161,6 +161,7 @@
   bool m_accessOngoing;
   Ptr<const Packet> m_currentPacket;
   WifiMacHeader m_currentHdr;
+  uint8_t m_currentRetry;
   uint8_t m_fragmentNumber;
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/dot11s-codes.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,89 @@
+/* -*-  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: Aleksey Kovalenko <kovalenko@iitp.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef DOT11S_CODES_H
+#define DOT11S_CODES_H
+
+namespace ns3 {
+
+enum dot11sElementID {
+	MESH_CONFIGURATION = 18,
+	MESH_ID,
+	LINK_METRIC_REPORT,
+	CONGESTION_NOTIFICATION,
+	PEER_LINK_MANAGEMENT,
+	MESH_CHANNEL_SWITCH_ANNOUNCEMENT,
+	MESH_TIM,
+	AWAKE_WINDOW,
+	SYNCHRONIZATION_PROTOCOL,
+	BEACON_TIMING,
+	MDAOP_SETUP_REQUEST,
+	MDAOP_SETUP_REPLY,
+	MDAOP_ADVERTISEMENT,
+	MDAOP_SET_TEARDOWN,
+	CONNECTIVITY_REPORT,
+	PORTAL_ANNOUNCEMENT,
+	ROOT_ANNOUCEMENT,
+	PATH_REQUEST,
+	PATH_REPLY,
+	PATH_ERROR,
+	PROXY_UPDATE,
+	PROXY_UPDATE_CONFIRMATION,
+	MSCIE,
+	MSAIE,
+};
+
+enum dot11sReasonCode {
+	PEER_LINK_CANCELLED,
+	MESH_MAX_PEERS,
+	MESH_CAPABILITY_POLICY_VIOLATION,
+	MESH_CLOSE_RCVD,
+	MESH_MAX_RETRIES,
+	MESH_CONFIRM_TIMEOUT,
+	MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS,
+	MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE,
+	MESH_SECURITY_FAILED_VERIFICATION,
+	MESH_INVALID_GTK,
+	MESH_MISMATCH_GTK,
+	MESH_INCONSISTENT_PARAMETERS,
+	MESH_CONFIGURATION_POLICY_VIOLATION,
+	DOT11S_REASON_RESERVED,
+};
+
+enum dot11sStatusCode {
+	PEAR_LINK_ESTABLISHED,
+	PEAR_LINK_CLOSED,
+	NO_LISTED_KEY_HOLDER,
+	MESH_KEY_HANDSHAKE_MALFORMED,
+	PEAR_LINK_MAX_RETRIES,
+	PEAR_LINK_NO_PMK,
+	PEAR_LINK_ALT_PMK,
+	PEAR_LINK_NO_AKM,
+	PEAR_LINK_ALT_AKM,
+	PEAR_LINK_NO_KDF,
+	PEAR_LINK_SA_ESTABLISHED,
+	AUTHENTICATION_REJECTED_CLOGGING,
+	DOT11S_STATUS_RESERVED,
+};
+
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/dot11s-parameters.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -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: Aleksey Kovalenko <kovalenko@iitp.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ns3/dot11s-parameters.h"
+
+namespace ns3
+{
+
+uint8_t dot11sParameters::dot11MeshMaxRetries      = 4;
+Time    dot11sParameters::dot11MeshRetryTimeout    = TU_TO_TIME(40);
+Time    dot11sParameters::dot11MeshHoldingTimeout  = TU_TO_TIME(40);
+Time    dot11sParameters::dot11MeshConfirmTimeout  = TU_TO_TIME(40);
+
+
+uint8_t dot11sParameters::dot11MeshHWMPmaxPREQretries           = 3;
+Time    dot11sParameters::dot11MeshHWMPnetDiameterTraversalTime = TU_TO_TIME(10);
+Time    dot11sParameters::dot11MeshHWMPpreqMinInterval          = TU_TO_TIME(100);
+Time    dot11sParameters::dot11MeshHWMPperrMinInterval          = TU_TO_TIME(100);
+Time    dot11sParameters::dot11MeshHWMPactiveRootTimeout        = TU_TO_TIME(5000);
+Time    dot11sParameters::dot11MeshHWMPactivePathTimeout        = TU_TO_TIME(5000);
+Time    dot11sParameters::dot11MeshHWMPpathToRootInterval       = TU_TO_TIME(5000);
+Time    dot11sParameters::dot11MeshHWMPrannInterval             = TU_TO_TIME(1000);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/dot11s-parameters.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,53 @@
+/* -*-  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: Aleksey Kovalenko <kovalenko@iitp.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef DOT11S_PARAMETERS_H
+#define DOT11S_PARAMETERS_H
+#include "ns3/uinteger.h" 
+#include "ns3/nstime.h"
+
+namespace ns3
+{
+
+#define TU_TO_TIME(x)	MicroSeconds(x*1024)
+#define TIME_TO_TU(x)	x.GetMicroSeconds()/1024
+
+struct dot11sParameters
+{
+	/** Peer Link  */
+	static uint8_t	dot11MeshMaxRetries;
+	static Time	dot11MeshRetryTimeout;
+	static Time	dot11MeshHoldingTimeout;
+	static Time	dot11MeshConfirmTimeout;
+	/** HWMP */
+	static uint8_t	dot11MeshHWMPmaxPREQretries;
+	static Time	dot11MeshHWMPnetDiameterTraversalTime;
+	static Time	dot11MeshHWMPpreqMinInterval;
+	static Time	dot11MeshHWMPperrMinInterval;
+	static Time	dot11MeshHWMPactiveRootTimeout;
+	static Time	dot11MeshHWMPactivePathTimeout;
+	static Time	dot11MeshHWMPpathToRootInterval;
+	static Time	dot11MeshHWMPrannInterval;
+};
+
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/dot11s-peer-management-element.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,134 @@
+/* -*-  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 "dot11s-peer-management-element.h"
+#include "ns3/assert.h"
+
+
+//NS_LOG_COMPONENT_DEFINE ("MeshPeerLinkManagementelement");
+
+namespace ns3 {
+
+PeerLinkManagementElement::PeerLinkManagementElement ():
+	m_length(0),
+  m_subtype(PEER_OPEN),
+	m_localLinkId(0),
+	m_peerLinkId(0),
+	m_reasonCode(DOT11S_REASON_RESERVED)
+{}
+
+
+void 
+PeerLinkManagementElement::SetPeerOpen(uint16_t localLinkId)
+{
+  m_length = 3; 
+  m_subtype=PEER_OPEN;
+  m_localLinkId = localLinkId;
+}
+void 
+PeerLinkManagementElement::SetPeerClose(uint16_t localLinkId, uint16_t peerLinkId, dot11sReasonCode reasonCode)
+{
+  m_length = 7; 
+  m_subtype=PEER_CLOSE;
+  m_localLinkId = localLinkId;
+  m_peerLinkId = peerLinkId;
+  m_reasonCode = reasonCode;
+}
+
+void
+PeerLinkManagementElement::SetPeerConfirm(uint16_t localLinkId, uint16_t peerLinkId)
+{
+  m_length = 5; 
+  m_subtype=PEER_CONFIRM;
+  m_localLinkId = localLinkId;
+  m_peerLinkId = peerLinkId;
+}
+
+dot11sReasonCode
+PeerLinkManagementElement::GetReasonCode() const
+{
+	return m_reasonCode;
+}
+
+uint16_t
+PeerLinkManagementElement::GetLocalLinkId() const
+{
+	return m_localLinkId;
+}
+
+uint16_t
+PeerLinkManagementElement::GetPeerLinkId() const
+{
+	return m_peerLinkId;
+}
+
+uint32_t
+PeerLinkManagementElement::GetSerializedSize (void) const
+{
+	return m_length+2;
+}
+
+bool
+PeerLinkManagementElement::SubtypeIsOpen() const
+{
+	return (m_subtype == PEER_OPEN);
+}
+bool
+PeerLinkManagementElement::SubtypeIsClose() const
+{
+	return (m_subtype == PEER_CLOSE);
+}
+bool
+PeerLinkManagementElement::SubtypeIsConfirm() const
+{
+	return (m_subtype == PEER_CONFIRM);
+}
+
+Buffer::Iterator
+PeerLinkManagementElement::Serialize (Buffer::Iterator i) const
+{
+	i.WriteU8(PEER_LINK_MANAGEMENT);
+	i.WriteU8(m_length);
+	i.WriteU8(m_subtype);
+	i.WriteHtonU16(m_localLinkId);
+	if(m_length > 3)
+		i.WriteHtonU16(m_peerLinkId);
+	if(m_length > 5)
+		i.WriteHtonU16(m_reasonCode);
+	return i;
+}
+Buffer::Iterator
+PeerLinkManagementElement::Deserialize (Buffer::Iterator i)
+{
+	dot11sElementID		ElementId;
+	ElementId	= (dot11sElementID)i.ReadU8();
+	NS_ASSERT(ElementId == PEER_LINK_MANAGEMENT);
+	m_length		= i.ReadU8();
+	m_subtype		= i.ReadU8();
+	m_localLinkId 	= i.ReadNtohU16();
+	if(m_length > 3)
+		m_peerLinkId	= i.ReadNtohU16();
+	if(m_length > 5)
+		m_reasonCode	= (dot11sReasonCode)i.ReadNtohU16();
+	return i;
+}
+} //namespace NS3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/dot11s-peer-management-element.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,66 @@
+/* -*-  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	<stdint.h>
+#include	"ns3/buffer.h"
+#include	"dot11s-codes.h"
+
+namespace ns3
+{
+class PeerLinkManagementElement
+{
+	public:
+		enum Subtype {
+			PEER_OPEN    = 0,
+			PEER_CLOSE   = 1,
+			PEER_CONFIRM = 2,
+		};
+	public:
+		PeerLinkManagementElement ();
+		
+		void			SetPeerOpen(uint16_t localLinkId);
+		void			SetPeerClose(uint16_t localLinkID, uint16_t peerLinkId, dot11sReasonCode reasonCode);
+		void			SetPeerConfirm(uint16_t localLinkID, uint16_t peerLinkId);
+	
+		dot11sReasonCode	GetReasonCode() const;
+		uint16_t		GetLocalLinkId() const;
+		uint16_t		GetPeerLinkId() const;
+		bool			SubtypeIsOpen() const;
+		bool			SubtypeIsClose() const;
+		bool			SubtypeIsConfirm() const ;
+
+		uint32_t		GetSerializedSize (void) const;
+		Buffer::Iterator	Serialize (Buffer::Iterator i) const;
+		Buffer::Iterator	Deserialize (Buffer::Iterator i);
+	private:
+		uint8_t			m_length;
+		uint8_t			m_subtype;
+		uint16_t		m_localLinkId;	//always is present
+		uint16_t		m_peerLinkId;	//only in confirm and may be present in close frame
+		dot11sReasonCode	m_reasonCode;	//only in close frame
+};
+} //namespace NS3
+#endif
+		  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-configuration-element.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,178 @@
+/* -*-  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 "mesh-configuration-element.h"
+#include "ns3/assert.h"
+#include "dot11s-codes.h"
+
+//NS_LOG_COMPONENT_DEFINE ("MeshConfigurationElement");
+
+namespace ns3 {
+
+dot11sMeshCapability::dot11sMeshCapability():
+  acceptPeerLinks(true),
+  MDAEnabled(false),
+  forwarding(true),
+  beaconTimingReport(false),
+  TBTTAdjustment(false),
+  powerSaveLevel(false)
+{}
+
+uint32_t	dot11sMeshCapability::GetSerializedSize (void) const
+{
+  return 2;
+}
+	
+Buffer::Iterator	dot11sMeshCapability::Serialize (Buffer::Iterator i) const
+{
+  uint16_t result = 0;
+  if(acceptPeerLinks)
+    result |= 1 << 0;
+  if(MDAEnabled)
+    result |= 1 << 1;
+  if(forwarding)
+    result |= 1 << 2;
+  if(beaconTimingReport)
+    result |= 1 << 3;
+  if(TBTTAdjustment)
+    result |= 1 << 4;
+  if(powerSaveLevel)
+    result |= 1 << 5;
+	i.WriteHtonU16(result);
+  return i;
+}
+
+Buffer::Iterator	dot11sMeshCapability::Deserialize (Buffer::Iterator i)
+{
+  uint16_t  cap = i.ReadNtohU16();
+  acceptPeerLinks = Is(cap,0);
+  MDAEnabled = Is(cap,1);
+  forwarding = Is(cap,2);
+  beaconTimingReport = Is(cap,3);
+  TBTTAdjustment = Is(cap,4);
+  powerSaveLevel = Is(cap,5);
+  return i;
+}
+
+bool dot11sMeshCapability::Is(uint16_t cap, uint8_t n) const 
+{
+  uint16_t mask = 1<<n;
+  return (cap & mask) == mask;
+}
+
+MeshConfigurationElement::MeshConfigurationElement ():
+  m_APSId(PROTOCOL_HWMP),
+  m_APSMId(METRIC_AIRTIME),
+  m_CCMId(CONGESTION_DEFAULT),
+  m_CP(CHANNEL_PRECEDENCE_OFF)
+{}
+
+uint32_t
+MeshConfigurationElement::GetSerializedSize (void) const
+{
+	return  1 // ID
+		+ 1 // Length
+		+ 1 // Version
+		+ 4 // APSPId
+		+ 4 // APSMId
+		+ 4 // CCMId
+		+ 4 // CP
+		+ m_meshCap.GetSerializedSize()
+		;
+}
+
+Buffer::Iterator
+MeshConfigurationElement::Serialize (Buffer::Iterator i) const
+{
+
+	i.WriteU8 (MESH_CONFIGURATION);
+	i.WriteU8 (GetSerializedSize());	// Length
+	i.WriteU8 (1);	//Version
+	// Active Path Selection Protocol ID:
+	i.WriteHtonU32(m_APSId);
+	// Active Path Metric ID:
+	i.WriteHtonU32(m_APSMId);
+	// Congestion Control Mode ID:
+	i.WriteU32(m_CCMId);
+	// Channel Precedence:
+	i.WriteU32(m_CP);
+	i = m_meshCap.Serialize(i);
+	return i;
+}
+
+Buffer::Iterator
+MeshConfigurationElement::Deserialize (Buffer::Iterator i)
+{
+
+	uint8_t	elementId;
+	uint8_t 	size;
+	uint8_t	version;
+	elementId	= i.ReadU8 ();
+	
+	NS_ASSERT (elementId == MESH_CONFIGURATION);
+	
+	size		= i.ReadU8 ();
+	version		= i.ReadU8();
+	// Active Path Selection Protocol ID:
+	m_APSId		= (dot11sPathSelectionProtocol)i.ReadNtohU32();
+	// Active Path Metric ID:
+	m_APSMId	= (dot11sPathSelectionMetric)i.ReadNtohU32();
+	// Congestion Control Mode ID:
+	m_CCMId		= (dot11sCongestionControlMode)i.ReadU32();
+	// Channel Precedence:
+	m_CP		= (dot11sChannelPrecedence)i.ReadU32();
+	i = m_meshCap.Deserialize(i);
+	return i;
+
+
+}
+
+void
+MeshConfigurationElement::SetRouting(dot11sPathSelectionProtocol routingId)
+{
+	m_APSId =  routingId ;
+}
+
+void
+MeshConfigurationElement::SetMetric(dot11sPathSelectionMetric metricId)
+{
+	m_APSMId =  metricId;
+}
+
+bool
+MeshConfigurationElement::IsHWMP(void)
+{
+	return (m_APSId == PROTOCOL_HWMP);
+}
+
+bool
+MeshConfigurationElement::IsAirtime(void)
+{
+	return (m_APSMId  == METRIC_AIRTIME);
+}
+
+dot11sMeshCapability const& MeshConfigurationElement::MeshCapability()
+{
+  return m_meshCap;
+}
+
+} //namespace NS3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-configuration-element.h	Sat Feb 28 14:21:05 2009 +0300
@@ -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_CONFIGURATION_H
+#define	MESH_CONFIGURATION_H
+
+#include	<stdint.h>
+#include	"ns3/buffer.h"
+
+namespace ns3
+{
+
+enum dot11sPathSelectionProtocol
+{
+  PROTOCOL_HWMP = 0x000fac00,
+  PROTOCOL_NULL = 0x000facff,
+};
+
+enum dot11sPathSelectionMetric
+{
+  METRIC_AIRTIME = 0x000fac00,
+  METRIC_NULL    = 0x000facff,
+};
+
+enum dot11sCongestionControlMode
+{
+  CONGESTION_DEFAULT = 0x000fac00,
+  CONGESTION_NULL    = 0x000facff,
+};
+
+enum dot11sChannelPrecedence 
+{
+  CHANNEL_PRECEDENCE_OFF = 0x000fac00,
+};
+
+
+class dot11sMeshCapability
+{
+  public:
+  dot11sMeshCapability();
+  uint32_t		GetSerializedSize (void) const;
+	Buffer::Iterator	Serialize (Buffer::Iterator i) const;
+	Buffer::Iterator	Deserialize (Buffer::Iterator i);
+  bool acceptPeerLinks;
+  bool MDAEnabled;
+  bool forwarding;
+  bool beaconTimingReport;
+  bool TBTTAdjustment;
+  bool powerSaveLevel;
+  private:
+  bool Is(uint16_t cap,uint8_t n) const;
+};
+
+class MeshConfigurationElement
+{
+	public:
+	MeshConfigurationElement();
+	void			SetRouting(dot11sPathSelectionProtocol routingId);
+	void			SetMetric(dot11sPathSelectionMetric metricId);
+	bool			IsHWMP(void);
+	bool			IsAirtime(void);
+
+  dot11sMeshCapability const& MeshCapability();
+
+	uint32_t		GetSerializedSize (void) const;
+	Buffer::Iterator	Serialize (Buffer::Iterator i) const;
+	Buffer::Iterator	Deserialize (Buffer::Iterator i);
+	// TODO: Release and fill other fields in configuration
+	// element
+	private:
+		/** Active Path Selection Protocol ID */
+		dot11sPathSelectionProtocol	m_APSId;
+		/** Active Path Metric ID */
+		dot11sPathSelectionMetric	  m_APSMId;
+		/** Congestion Control Mode ID */
+		dot11sCongestionControlMode	m_CCMId;
+		/* Channel Precedence */
+		dot11sChannelPrecedence	m_CP;
+		dot11sMeshCapability	m_meshCap;
+};
+} //name space NS3
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-mgt-headers.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,226 @@
+/* -*-  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>
+ *          Yana Podkosova <yanapdk@rambler.ru>
+ *          Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#include "mesh-mgt-headers.h"
+#include "ns3/address-utils.h"
+#include "ns3/simulator.h"
+#include "ns3/assert.h"
+
+namespace ns3
+{
+/***********************************************************
+*          PeerLinkOpen frame:
+************************************************************/
+NS_OBJECT_ENSURE_REGISTERED (MeshMgtPeerLinkManFrame);
+
+MeshMgtPeerLinkManFrame::MeshMgtPeerLinkManFrame()
+{
+}
+
+void
+MeshMgtPeerLinkManFrame::SetAid(uint16_t aid)
+{
+	Aid = aid;
+}
+
+void
+MeshMgtPeerLinkManFrame::SetSupportedRates(SupportedRates rates)
+{
+	Rates = rates;
+}
+
+void
+MeshMgtPeerLinkManFrame::SetQosField(uint16_t qos)
+{
+	QoS= qos;
+}
+
+void
+MeshMgtPeerLinkManFrame::SetMeshId(Ssid Id)
+{
+	MeshId = Id;
+}
+
+void
+MeshMgtPeerLinkManFrame::SetMeshConfigurationElement(MeshConfigurationElement MeshConf)
+{
+	MeshConfig = MeshConf;
+}
+
+void
+MeshMgtPeerLinkManFrame::SetPeerLinkManagementElement(PeerLinkManagementElement MeshPeerElement)
+{
+	PeerLinkMan = MeshPeerElement;
+}
+
+uint16_t
+MeshMgtPeerLinkManFrame::GetAid()
+{
+	return Aid;
+}
+
+SupportedRates
+MeshMgtPeerLinkManFrame::GetSupportedRates()
+{
+	return Rates;
+}
+
+uint16_t
+MeshMgtPeerLinkManFrame::GetQosField()
+{
+	return QoS;
+}
+
+Ssid
+MeshMgtPeerLinkManFrame::GetMeshId()
+{
+	return MeshId;
+}
+
+MeshConfigurationElement
+MeshMgtPeerLinkManFrame::GetMeshConfigurationElement()
+{
+	return MeshConfig;
+}
+
+PeerLinkManagementElement
+MeshMgtPeerLinkManFrame::GetPeerLinkManagementElement()
+{
+	return PeerLinkMan;
+}
+
+TypeId
+MeshMgtPeerLinkManFrame::GetTypeId(void)
+{
+	static TypeId tid = 
+		TypeId ("ns3::MeshMgtPeerLinkManFrame")
+		.SetParent<Header> ()
+		.AddConstructor<MeshMgtPeerLinkManFrame> ()
+		;
+	return tid;
+}
+
+TypeId
+MeshMgtPeerLinkManFrame::GetInstanceTypeId(void) const
+{
+	return GetTypeId();
+}
+
+void
+MeshMgtPeerLinkManFrame::Print(std::ostream &os) const
+{
+	//TODO:fill this method
+}
+
+uint32_t
+MeshMgtPeerLinkManFrame::GetSerializedSize(void) const
+{
+	uint32_t size = 1; //Subtype
+	if(MESH_MGT_HEADER_PEER_CONFIRM == Subtype)
+		size +=2; //AID of remote peer
+	if(MESH_MGT_HEADER_PEER_CLOSE != Subtype)
+	{
+		size += Rates.GetSerializedSize ();
+		size +=2;
+		size += MeshId.GetSerializedSize ();
+		size += MeshConfig.GetSerializedSize ();
+	}
+	size += PeerLinkMan.GetSerializedSize ();
+	return size;
+}
+
+void
+MeshMgtPeerLinkManFrame::Serialize(Buffer::Iterator start) const
+{
+	Buffer::Iterator i = start;
+	i.WriteU8(Subtype); //Like a Category in Standart
+	if(MESH_MGT_HEADER_PEER_CONFIRM == Subtype)
+		
+		i.WriteHtonU16(Aid);
+	if(MESH_MGT_HEADER_PEER_CLOSE != Subtype)
+	{
+		i = Rates.Serialize(i);
+		//now QoS capabilities
+		i.WriteHtonU16(QoS);
+		i = MeshId.Serialize (i);
+		i = MeshConfig.Serialize (i);
+	}
+	i = PeerLinkMan.Serialize (i);
+}
+
+uint32_t
+MeshMgtPeerLinkManFrame::Deserialize(Buffer::Iterator start)
+{
+	Buffer::Iterator i = start;
+	Subtype = i.ReadU8();
+	if(MESH_MGT_HEADER_PEER_CONFIRM == Subtype)
+		Aid = i.ReadNtohU16();
+	if(MESH_MGT_HEADER_PEER_CLOSE != Subtype)
+	{
+		i = Rates.Deserialize(i);
+		QoS = i.ReadNtohU16();
+		i = MeshId.Deserialize (i);
+		i = MeshConfig.Deserialize (i);
+	}
+	i = PeerLinkMan.Deserialize (i);
+	return i.GetDistanceFrom (start);
+}
+void
+MeshMgtPeerLinkManFrame::SetOpen()
+{
+	Subtype = MESH_MGT_HEADER_PEER_OPEN;
+}
+
+void
+MeshMgtPeerLinkManFrame::SetConfirm()
+{
+	Subtype = MESH_MGT_HEADER_PEER_CONFIRM;
+}
+
+void
+MeshMgtPeerLinkManFrame::SetClose()
+{
+	Subtype = MESH_MGT_HEADER_PEER_CLOSE;
+}
+
+bool
+MeshMgtPeerLinkManFrame::IsOpen()
+{
+	return (Subtype==MESH_MGT_HEADER_PEER_OPEN);
+}
+
+bool
+MeshMgtPeerLinkManFrame::IsConfirm()
+{
+	return (Subtype==MESH_MGT_HEADER_PEER_CONFIRM);
+}
+
+bool
+MeshMgtPeerLinkManFrame::IsClose()
+{
+	return (Subtype==MESH_MGT_HEADER_PEER_CLOSE);
+}
+
+} //namespace NS3
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-mgt-headers.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,95 @@
+/* -*-  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>
+ *          Yana Podkosova <yanapdk@rambler.ru>
+ *          Aleksey Kovalenko <kovalenko@iitp.ru>
+ */
+
+
+#ifndef MESH_MGT_HEADERS_H
+#define MESH_MGT_HEADERS_H
+
+#include <stdint.h>
+
+#include "ns3/header.h"
+#include "status-code.h"
+#include "dot11s-peer-management-element.h"
+#include "supported-rates.h"
+#include "mesh-configuration-element.h"
+#include "mesh-wifi-preq-information-element.h"
+#include "mesh-wifi-prep-information-element.h"
+#include "mesh-wifi-perr-information-element.h"
+#include "mesh-wifi-rann-information-element.h"
+#include "ssid.h"
+
+namespace ns3 {
+
+class MeshMgtPeerLinkManFrame :	public Header
+{
+	public:
+		MeshMgtPeerLinkManFrame ();
+		void				SetAid(uint16_t aid);
+		void				SetSupportedRates(SupportedRates rates);
+		void				SetQosField(uint16_t qos);
+		void				SetMeshId(Ssid Id);
+		void				SetMeshConfigurationElement(MeshConfigurationElement MeshConf);
+		void				SetPeerLinkManagementElement(PeerLinkManagementElement MeshPeerElement);
+
+		uint16_t			GetAid();
+		SupportedRates			GetSupportedRates();
+		uint16_t			GetQosField();
+		Ssid				GetMeshId();
+		MeshConfigurationElement	GetMeshConfigurationElement();
+		PeerLinkManagementElement	GetPeerLinkManagementElement();
+
+		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);
+		//Subtype defining methods:
+		void				SetOpen();
+		void				SetConfirm();
+		void				SetClose();
+
+		bool				IsOpen();
+		bool				IsConfirm();
+		bool				IsClose();
+
+	private:
+		uint8_t			Subtype;
+		static const uint8_t	MESH_MGT_HEADER_PEER_OPEN = 1;
+		static const uint8_t	MESH_MGT_HEADER_PEER_CONFIRM = 2;
+		static const uint8_t	MESH_MGT_HEADER_PEER_CLOSE = 3;
+		// Standart is also requires a ReasonCode to be within
+		// PeerLinkClose frame format, but it is present within
+		// PeerLinkManagementElement, so we did not duplicate
+		// it.
+		uint16_t			Aid;		//only in Confirm
+		SupportedRates			Rates;		//only in Open and Confirm
+		uint16_t			QoS;		//only in Open and Confirm
+		Ssid				MeshId;		//only in Open and Confirm
+		MeshConfigurationElement	MeshConfig;	//only in Open and Confirm
+		PeerLinkManagementElement	PeerLinkMan;	//in all types of frames
+};
+
+}//namespace NS3
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-beacon-timing-element.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,195 @@
+/* -*-  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 "mesh-wifi-beacon-timing-element.h"
+#define ELEMENT_ID (19)
+namespace ns3 {
+/*******************************************
+ * WifiBeaconTimingElementUnit
+ *******************************************/
+WifiBeaconTimingElementUnit::WifiBeaconTimingElementUnit()
+{
+	AID = 0;
+	LastBeacon = 0;
+	BeaconInterval = 0;
+}
+
+void
+WifiBeaconTimingElementUnit::SetAID(uint8_t aid)
+{
+	AID = aid;
+}
+
+void
+WifiBeaconTimingElementUnit::SetLastBeacon(uint16_t last_beacon)
+{
+	LastBeacon = last_beacon;
+}
+
+void
+WifiBeaconTimingElementUnit::SetBeaconInterval(uint16_t beacon_interval)
+{
+	BeaconInterval = beacon_interval;
+}
+
+uint8_t
+WifiBeaconTimingElementUnit::GetAID()
+{
+	return AID;
+}
+
+uint16_t
+WifiBeaconTimingElementUnit::GetLastBeacon()
+{
+	return LastBeacon;
+}
+
+uint16_t
+WifiBeaconTimingElementUnit::GetBeaconInterval()
+{
+	return BeaconInterval;
+}
+
+/*******************************************
+ * WifiBeaconTimingElement
+ *******************************************/
+WifiBeaconTimingElement::WifiBeaconTimingElement()
+{
+	m_maxSize = DEFAULT_MAX_SIZE;
+	m_numOfUnits = 0;
+}
+
+NeighboursTimingUnitsList
+WifiBeaconTimingElement::GetNeighboursTimingElementsList()
+{
+	return m_neighbours;
+}
+
+void
+WifiBeaconTimingElement::AddNeighboursTimingElementUnit(
+		uint16_t	aid,
+		Time		last_beacon,	//MicroSeconds!
+		Time		beacon_interval	//MicroSeconds!
+		)
+{
+	//Firs we lookup if this element already exists
+	for(NeighboursTimingUnitsList::iterator i = m_neighbours.begin(); i!= m_neighbours.end(); i++)
+		if(
+				   ((*i)->GetAID() == AID_TO_U8(aid))
+				&& ((*i)->GetLastBeacon() == TIMESTAMP_TO_U16(last_beacon))
+				&& ((*i)->GetBeaconInterval() == BEACON_INTERVAL_TO_U16(beacon_interval))
+				)
+			return;
+	Ptr<WifiBeaconTimingElementUnit>new_element = Create<WifiBeaconTimingElementUnit>();
+	new_element->SetAID(AID_TO_U8(aid));
+	new_element->SetLastBeacon(TIMESTAMP_TO_U16(last_beacon));
+	new_element->SetBeaconInterval(BEACON_INTERVAL_TO_U16(beacon_interval));
+	m_neighbours.push_back(new_element);
+	m_numOfUnits++;
+}
+
+void
+WifiBeaconTimingElement::DelNeighboursTimingElementUnit(
+		uint16_t	aid,
+		Time		last_beacon,	//MicroSeconds!
+		Time		beacon_interval	//MicroSeconds!
+		)
+{
+	for(NeighboursTimingUnitsList::iterator i = m_neighbours.begin(); i!= m_neighbours.end(); i++)
+		if(
+				   ((*i)->GetAID() == AID_TO_U8(aid))
+				&& ((*i)->GetLastBeacon() == TIMESTAMP_TO_U16(last_beacon))
+				&& ((*i)->GetBeaconInterval() == BEACON_INTERVAL_TO_U16(beacon_interval))
+				)
+		{
+			m_neighbours.erase(i);
+			m_numOfUnits--;
+			break;
+		}
+
+}
+
+void
+WifiBeaconTimingElement::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();
+
+}
+
+uint32_t
+WifiBeaconTimingElement::GetSerializedSize (void) const
+{
+	return (2+5*m_numOfUnits > m_maxSize) ? 2+((m_maxSize-2)/5)*5 : 2+5*m_numOfUnits;
+}
+Buffer::Iterator
+WifiBeaconTimingElement::Serialize (Buffer::Iterator i) const
+{
+	uint8_t can_be_written = (2+5*m_numOfUnits > m_maxSize) ? ((m_maxSize-2)/5) : m_numOfUnits;
+	int actually_written = 0;
+	i.WriteU8 (ELEMENT_ID);
+	i.WriteU8 (can_be_written);
+	for(NeighboursTimingUnitsList::const_iterator j = m_neighbours.begin(); j!= m_neighbours.end(); j++)
+	{
+		i.WriteU8	((*j)->GetAID());
+		i.WriteHtonU16	((*j)->GetLastBeacon());
+		i.WriteHtonU16	((*j)->GetBeaconInterval());
+		actually_written++;
+		if(actually_written > can_be_written)
+			break;
+	}
+	if(can_be_written < m_numOfUnits)
+	{
+		//move written units to the end of our list, so they
+		//can be sent in timing element with next beacon
+		//TODO:swap elements
+		
+	}
+	return i;
+}
+Buffer::Iterator
+WifiBeaconTimingElement::Deserialize (Buffer::Iterator i)
+{
+	uint8_t elementId;
+	uint8_t num_to_read = 0;
+	int j;
+	elementId = i.ReadU8();
+	NS_ASSERT(elementId == ELEMENT_ID);
+	num_to_read = i.ReadU8();
+	for(j=0;j<num_to_read; j++)
+	{		
+		Ptr<WifiBeaconTimingElementUnit> new_element = Create<WifiBeaconTimingElementUnit>();
+		new_element->SetAID(i.ReadU8());
+		new_element->SetLastBeacon(i.ReadNtohU16());
+		new_element->SetBeaconInterval(i.ReadNtohU16());
+		m_neighbours.push_back(new_element);
+	}
+	return i;
+};
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-beacon-timing-element.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,103 @@
+/* -*-  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	<stdint.h>
+#include	"ns3/buffer.h"
+#include	"ns3/nstime.h"
+#include	<list>
+namespace ns3
+{
+class WifiBeaconTimingElementUnit : public RefCountBase
+{
+	public:
+		WifiBeaconTimingElementUnit();
+		void	SetAID(uint8_t aid);
+		void	SetLastBeacon(uint16_t last_beacon);
+		void	SetBeaconInterval(uint16_t beacon_interval);
+
+		uint8_t	GetAID();
+		uint16_t	GetLastBeacon();
+		uint16_t	GetBeaconInterval();
+	private:
+		//Least significant octet of AID:
+		uint8_t	AID;
+		//Last time we received a beacon in accordance with a
+		//local TSF measured in 256 microseconds unit:
+		uint16_t	LastBeacon;
+		//Beacon interval of remote mesh point:
+		uint16_t	BeaconInterval;
+};
+//This type is a list of timing elements obtained from neigbours with their beacons:
+typedef Ptr<WifiBeaconTimingElementUnit>		WifiBeaconTimingElementPointer;
+typedef std::list<WifiBeaconTimingElementPointer>	NeighboursTimingUnitsList;
+
+class WifiBeaconTimingElement
+{
+	public:
+		WifiBeaconTimingElement();
+		//This methods are needed for beacon collision
+		//avoidance module:
+		NeighboursTimingUnitsList
+					GetNeighboursTimingElementsList();
+		//The arguments of the following methods are different
+		//from internalBeaconTimingElementUnint. This was made
+		//for better communication with peer manager.
+		//BeaconTimingElement class should convert it into
+		//proper types:
+		void			AddNeighboursTimingElementUnit(
+				uint16_t	aid,
+				Time		last_beacon,	//MicroSeconds!
+				Time		beacon_interval	//MicroSeconds!
+				);
+		void			DelNeighboursTimingElementUnit(
+				uint16_t	aid,
+				Time		last_beacon,	//MicroSeconds!
+				Time		beacon_interval	//MicroSeconds!
+				);
+		void			ClearTimingElement();
+		uint16_t TIMESTAMP_TO_U16(Time x)
+		{
+			return ((uint16_t)((x.GetMicroSeconds() >> 8)&0xffff));
+		};
+		uint16_t BEACON_INTERVAL_TO_U16(Time x)
+		{
+			return ((uint16_t)(x.GetMicroSeconds() >>10)&0xffff);
+		};
+		uint8_t AID_TO_U8(uint16_t x)
+		{
+			return (uint8_t)(x&0xff);
+		};
+		//Serialize-deserialize methods:
+		uint32_t		GetSerializedSize (void) const;
+		Buffer::Iterator	Serialize (Buffer::Iterator i) const;
+		Buffer::Iterator	Deserialize (Buffer::Iterator i);
+	private:
+		NeighboursTimingUnitsList		m_neighbours;
+		//The maximum size of this element:
+		const static uint16_t	DEFAULT_MAX_SIZE = 255*5 +2;
+		uint16_t		m_maxSize;
+		uint16_t		m_numOfUnits;
+};
+}//namespace ns3
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-mac.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,957 @@
+/* -*-  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>
+ *          Ivan Pustogarov <chinsa1@rambler.ru>
+ *          Evgeny Khorov <horov@frtk.ru>
+ */
+
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/node.h"
+#include "ns3/random-variable.h"
+
+#include "mesh-wifi-mac.h"
+#include "dca-txop.h"
+#include "wifi-mac-header.h"
+#include "mgt-headers.h"
+#include "wifi-phy.h"
+#include "dcf-manager.h"
+#include "mac-rx-middle.h"
+#include "mac-low.h"
+#include "ns3/tx-statistics.h"
+#include "ns3/hwmp.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshWifiMac");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (MeshWifiMac);
+
+TypeId
+MeshWifiMac::GetTypeId (void)
+{
+	static TypeId tid = TypeId ("ns3::MeshWifiMac")
+		.SetParent<WifiMac> ()
+		.AddConstructor<MeshWifiMac> ()
+		.AddAttribute ("BeaconInterval", "Beacon Interval",
+				TimeValue (Seconds (1.0)),
+				MakeTimeAccessor (&MeshWifiMac::m_beaconInterval),
+				MakeTimeChecker ()
+				)
+		.AddAttribute ("RandomStart", "Window when beacon generating starts (uniform random) in seconds",
+				TimeValue (Seconds (0.1)),
+				MakeTimeAccessor (&MeshWifiMac::m_randomStart),
+				MakeTimeChecker ()
+				)
+		.AddAttribute ("SoftwareDelay", "Window of uniformely distributed random software handling delay",
+				TimeValue (MicroSeconds (500)),
+				MakeTimeAccessor (&MeshWifiMac::m_softwareDelay),
+				MakeTimeChecker ()
+				)
+		.AddAttribute ("BeaconGeneration", "Enable/Disable Beaconing.",
+				BooleanValue (true),
+				MakeBooleanAccessor (
+					&MeshWifiMac::SetBeaconGeneration,
+					&MeshWifiMac::GetBeaconGeneration
+					),
+					MakeBooleanChecker ()
+				);
+	return tid;
+}
+
+MeshWifiMac::MeshWifiMac ()
+{
+	NS_LOG_FUNCTION (this);
+	m_rxMiddle = new MacRxMiddle ();
+	m_rxMiddle->SetForwardCallback (MakeCallback (&MeshWifiMac::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);
+
+	m_VO = CreateObject<DcaTxop> ();
+	m_VO->SetLow (m_low);
+	m_VO->SetMinCw (3);
+	m_VO->SetMaxCw (7);
+	m_VO->SetManager (m_dcfManager);
+	m_VO->SetTxOkCallback (MakeCallback (&MeshWifiMac::TxOk, this));
+	m_VO->SetTxFailedCallback (MakeCallback (&MeshWifiMac::TxFailed, this));
+
+	m_BE = CreateObject<DcaTxop> ();
+	m_BE->SetLow (m_low);
+	m_BE->SetManager (m_dcfManager);
+	m_BE->SetTxOkCallback (MakeCallback (&MeshWifiMac::TxOk, this));
+	m_BE->SetTxFailedCallback (MakeCallback (&MeshWifiMac::TxFailed, this));
+}
+
+MeshWifiMac::~MeshWifiMac ()
+{
+	NS_LOG_FUNCTION (this);
+}
+/*
+ * Public Methods:
+ */
+void 
+MeshWifiMac::SetSlot (Time slotTime)
+{
+	NS_LOG_FUNCTION (this << slotTime);
+	m_dcfManager->SetSlot (slotTime);
+	m_slot = slotTime;
+}
+
+void 
+MeshWifiMac::SetSifs (Time sifs) 
+{
+	NS_LOG_FUNCTION (this << sifs); 
+	m_dcfManager->SetSifs (sifs);
+	m_sifs = sifs;
+}
+void 
+MeshWifiMac::SetAckTimeout (Time ackTimeout)
+{
+	m_low->SetAckTimeout (ackTimeout);
+}
+
+void 
+MeshWifiMac::SetCtsTimeout (Time ctsTimeout)
+{
+	m_low->SetCtsTimeout (ctsTimeout);
+}
+
+void 
+MeshWifiMac::SetPifs (Time pifs) 
+{
+	NS_LOG_FUNCTION (this << pifs); 
+	m_pifs = pifs;
+}
+void
+MeshWifiMac::SetEifsNoDifs (Time eifsNoDifs)
+{
+	NS_LOG_FUNCTION (this << eifsNoDifs);
+	m_dcfManager->SetEifsNoDifs (eifsNoDifs);
+	m_eifsNoDifs = eifsNoDifs;
+}
+
+Time 
+MeshWifiMac::GetSlot (void) const
+{
+	return m_slot;
+}
+
+Time 
+MeshWifiMac::GetSifs (void) const
+{
+	return m_sifs;
+}
+
+Time 
+MeshWifiMac::GetEifsNoDifs (void) const
+{
+	return m_eifsNoDifs;
+}
+
+Time 
+MeshWifiMac::GetAckTimeout (void) const
+{
+	return m_low->GetAckTimeout ();
+}
+
+Time 
+MeshWifiMac::GetCtsTimeout (void) const
+{
+	return m_low->GetCtsTimeout ();
+}
+
+Time 
+MeshWifiMac::GetPifs (void) const
+{
+	return m_low->GetPifs ();
+}
+
+void
+MeshWifiMac::SetWifiPhy (Ptr<WifiPhy> phy)
+{
+	NS_LOG_FUNCTION (this << phy);
+	m_phy = phy;
+	m_dcfManager->SetupPhyListener (phy);
+	m_low->SetPhy (phy);
+}
+
+void 
+MeshWifiMac::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> stationManager)
+{
+	NS_LOG_FUNCTION (this << stationManager);
+	m_stationManager = stationManager;
+	m_BE->SetWifiRemoteStationManager (stationManager);
+	m_VO->SetWifiRemoteStationManager (stationManager);
+	m_beaconDca->SetWifiRemoteStationManager (stationManager);
+	m_low->SetWifiRemoteStationManager (stationManager);
+}
+
+void
+MeshWifiMac::SetPeerLinkManager (Ptr<WifiPeerManager> manager)
+{
+  m_peerManager = manager;
+}
+
+void 
+MeshWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to, Mac48Address from)
+{
+	NS_LOG_FUNCTION (this << packet << to << from);
+	ForwardDown (packet, from, to);
+}
+
+void 
+MeshWifiMac::Enqueue (Ptr<const Packet> packet, Mac48Address to)
+{
+	NS_LOG_FUNCTION (this << packet << to);
+	ForwardDown (packet, m_low->GetAddress (), to);
+}
+
+bool 
+MeshWifiMac::SupportsSendFrom (void) const
+{
+	return true;
+}
+
+void 
+MeshWifiMac::SetForwardUpCallback (Callback<void,Ptr<Packet>, Mac48Address, Mac48Address> upCallback)
+{
+	NS_LOG_FUNCTION (this);
+	m_upCallback = upCallback;
+}
+
+void 
+MeshWifiMac::SetLinkUpCallback (Callback<void> linkUp)
+{
+	NS_LOG_FUNCTION (this);
+	if (!linkUp.IsNull ())
+	{
+		linkUp ();
+	}
+}
+
+void 
+MeshWifiMac::SetLinkDownCallback (Callback<void> linkDown)
+{
+	NS_LOG_FUNCTION (this);
+}
+
+Mac48Address 
+MeshWifiMac::GetAddress (void) const
+{
+	return m_address;
+}
+Mac48Address
+MeshWifiMac::GetBssid (void) const
+{
+	return m_address;
+}
+
+Ssid 
+MeshWifiMac::GetSsid (void) const
+{
+	return m_MeshId;
+}
+
+void 
+MeshWifiMac::SetAddress (Mac48Address address)
+{
+	NS_LOG_FUNCTION (address);
+	m_low->SetAddress(address);
+	m_address = address;
+}
+
+void 
+MeshWifiMac::SetSsid (Ssid ssid)
+{
+	NS_LOG_FUNCTION (ssid);
+	m_MeshId = ssid;
+}
+
+void 
+MeshWifiMac::SetBeaconInterval (Time interval)
+{
+	NS_LOG_FUNCTION (this << interval);
+	m_beaconInterval = interval;
+}
+
+void
+MeshWifiMac::DoDispose (void)
+{
+	delete m_rxMiddle;
+	delete m_dcfManager;
+	//Delete smart pointers:
+	m_beaconSendEvent.Cancel ();
+	m_beaconFormEvent.Cancel ();
+	m_low = 0;
+	m_BE = 0;
+	m_VO = 0;
+	m_beaconDca = 0;
+	m_phy = 0;
+        m_peerManager=0;
+	WifiMac::DoDispose ();
+}
+
+void 
+MeshWifiMac::ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst)
+{
+	NS_LOG_FUNCTION (this << packet << src);
+	m_upCallback (packet, src, dst);
+}
+
+void 
+MeshWifiMac::ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to)
+{
+	//TODO:Classify and queue
+	WifiMacHeader hdr;
+	Ptr<Packet> packet_to_send = packet->Copy();
+	WifiMeshHeader meshHdr;
+	//Address 1 we receive from HWMP tag
+	HwmpTag tag;
+	NS_ASSERT(packet->FindFirstMatchingTag(tag));
+	meshHdr.SetMeshTtl(tag.GetTtl());
+	meshHdr.SetMeshSeqno(tag.GetSeqno());
+#if 0
+	NS_LOG_DEBUG(
+			"TX Packet sa = "<<from<<
+			", da = "<<to<<
+			", ra = "<<tag.GetAddress()<<
+			", I am "<<GetAddress()<<
+			", ttl = "<<(int)meshHdr.GetMeshTtl()
+			);
+#endif
+	if(to!= Mac48Address::GetBroadcast())
+		NS_ASSERT(tag.GetAddress()!=Mac48Address::GetBroadcast());
+	hdr.SetTypeData ();
+	hdr.SetAddr1 (tag.GetAddress());
+	hdr.SetAddr2 (GetAddress ());
+	hdr.SetAddr3 (to);
+	hdr.SetAddr4(from);
+	hdr.SetDsFrom ();
+	hdr.SetDsTo ();
+	//TODO: classify should be fixed!
+	packet_to_send->AddHeader(meshHdr);
+	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 ();
+	}
+	m_BE->Queue (packet_to_send, hdr);
+}
+
+SupportedRates
+MeshWifiMac::GetSupportedRates (void) const
+{
+	// send 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;
+}
+
+void
+MeshWifiMac::SendOneBeacon (void)
+{
+	NS_LOG_FUNCTION (this);
+	NS_LOG_DEBUG(GetAddress()<<" is sending beacon");
+	//Software delay should never be bigger than beacon interval!
+	NS_ASSERT(!m_beaconSendEvent.IsRunning());
+	Time last_software_delay = m_beaconFormingRandomDelay;
+	MgtMeshBeaconHeader beacon;
+	beacon.SetSsid (GetSsid ());
+	beacon.SetSupportedRates (GetSupportedRates ());
+	beacon.SetBeaconIntervalUs (m_beaconInterval.GetMicroSeconds ());
+	beacon.SetWifiBeaconTimingElement(m_peerManager->GetWifiBeaconTimingElementForMyBeacon(GetAddress()));
+	m_beaconSendEvent = Simulator::Schedule(
+			m_beaconFormingRandomDelay,
+			&MeshWifiMac::QueueOneBeacon,
+			this,
+			beacon);
+	UniformVariable coefficient(0.0, m_beaconFormingRandomDelay.GetSeconds());
+	m_beaconFormingRandomDelay = Seconds(coefficient.GetValue());
+
+        //MBCA functionality, TODO: add the switch off/on MBCA mechanism capability
+        //Let's find when we send the next beacon
+        Time myNextTBTT = Simulator::Now ()+m_beaconInterval+last_software_delay;
+        //The mext function compares my TBTT with neighbor's TBTTs using timing elemnt
+        //and returns time shift for the next beacon if future collision is detected
+ 	Time nextBeaconShift = m_peerManager->GetNextBeaconShift(GetAddress(), myNextTBTT);
+
+	m_beaconFormEvent = Simulator::Schedule (m_beaconInterval-m_beaconFormingRandomDelay+last_software_delay+nextBeaconShift, &MeshWifiMac::SendOneBeacon, this);
+}
+
+void
+MeshWifiMac::QueueOneBeacon (MgtMeshBeaconHeader beacon_hdr)
+{
+	WifiMacHeader hdr;
+	hdr.SetBeacon ();
+	hdr.SetAddr1 (Mac48Address::GetBroadcast ());
+	hdr.SetAddr2 (GetAddress ());
+	hdr.SetAddr3 (GetAddress ());
+	hdr.SetDsNotFrom ();
+	hdr.SetDsNotTo ();
+	Ptr<Packet> packet = Create<Packet> ();
+
+	packet->AddHeader (beacon_hdr);
+	m_beaconDca->Queue(packet, hdr);
+	m_peerManager->SetSentBeaconTimers(
+			GetAddress(),
+			Simulator::Now (),
+			MicroSeconds(beacon_hdr.GetBeaconIntervalUs())
+			);
+
+}
+void
+MeshWifiMac::SetBeaconGeneration (bool enable)
+{
+	NS_LOG_FUNCTION (this << enable);
+	if (enable)
+	{
+		UniformVariable coefficient(0.0, m_randomStart.GetSeconds());
+		Time randomStart = Seconds(coefficient.GetValue());
+		// Beacons must be sent with a random delay,
+		// otherwise, they will all be broken
+		m_beaconFormEvent = Simulator::Schedule (randomStart, &MeshWifiMac::SendOneBeacon, this);
+	}
+	else
+		m_beaconFormEvent.Cancel ();
+}
+
+bool
+MeshWifiMac::GetBeaconGeneration (void) const
+{
+	return m_beaconFormEvent.IsRunning ();
+}
+
+void
+MeshWifiMac::TxOk (WifiMacHeader const &hdr)
+{
+}
+
+void
+MeshWifiMac::TxFailed (WifiMacHeader const &hdr)
+{
+}
+
+void 
+MeshWifiMac::Receive (Ptr<Packet> packet, WifiMacHeader const *hdr)
+{
+	if (hdr->IsBeacon ()) 
+	{
+		MgtMeshBeaconHeader beacon;
+		Mac48Address from = hdr->GetAddr2();
+		packet->RemoveHeader (beacon);
+		NS_LOG_DEBUG("Beacon received from "<<hdr->GetAddr2()<<
+				" to "<<GetAddress()<<
+				" at "<<Simulator::Now ().GetMicroSeconds ()<<
+				" microseconds");
+#if 0
+		NeighboursTimingUnitsList neighbours;
+		neighbours = beacon.GetWifiBeaconTimingElement().GetNeighboursTimingElementsList();
+		for(NeighboursTimingUnitsList::const_iterator j = neighbours.begin(); j!= neighbours.end(); j++)
+			fprintf(
+					stderr,
+					"neigbours:\nAID=%u, last_beacon=%u ,beacon_interval=%u\n",
+					(*j)->GetAID(),
+					(*j)->GetLastBeacon(),
+					(*j)->GetBeaconInterval()
+					);
+#endif
+		m_peerManager->SetReceivedBeaconTimers(
+				GetAddress(),
+				from,
+				Simulator::Now (),
+				MicroSeconds(beacon.GetBeaconIntervalUs()),
+				beacon.GetWifiBeaconTimingElement()
+				);
+		if(!beacon.GetSsid().IsEqual(GetSsid()))
+			return;
+		SupportedRates rates = beacon.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);
+				}
+			}
+		}
+		// TODO:Chack MeshConfigurationElement(now is nothing
+		// to be checked)
+		m_peerManager->AskIfOpenNeeded(GetAddress(), from);
+		return;
+	}
+	if(hdr->IsMultihopAction())
+	{
+		WifiMeshHeader meshHdr;
+		//no mesh header parameters are needed here:
+		//TODO: check TTL
+		packet->RemoveHeader(meshHdr);
+		WifiMeshMultihopActionHeader multihopHdr;
+		//parse multihop action header:
+		packet->RemoveHeader(multihopHdr);
+		WifiMeshMultihopActionHeader::ACTION_VALUE
+			actionValue = multihopHdr.GetAction();
+		switch(multihopHdr.GetCategory())
+		{
+			case WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT:
+			{
+				Mac48Address peerAddress; 
+				MeshMgtPeerLinkManFrame peer_frame;
+				if(hdr->GetAddr1 () != GetAddress ())
+					return;
+				peerAddress = hdr->GetAddr2();
+				packet->RemoveHeader (peer_frame);
+				if(actionValue.peerLink != WifiMeshMultihopActionHeader::PEER_LINK_CLOSE)
+				{
+					//check Supported Rates
+					SupportedRates rates = peer_frame.GetSupportedRates();
+					for (uint32_t i = 0; i < m_stationManager->GetNBasicModes (); i++)
+					{
+						WifiMode mode = m_stationManager->GetBasicMode (i);
+						if (!rates.IsSupportedRate (mode.GetDataRate ()))
+						{
+							m_peerManager->ConfigurationMismatch(GetAddress(), peerAddress);
+							return;
+						}
+					}
+					//Check SSID
+					if(!peer_frame.GetMeshId().IsEqual(GetSsid()))
+					{
+						m_peerManager->ConfigurationMismatch(GetAddress(), peerAddress);
+						return;
+					}
+				}
+				switch(actionValue.peerLink)
+				{
+					case WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM:
+						m_peerManager->SetConfirmReceived(
+								GetAddress(),
+								peerAddress,
+								peer_frame.GetAid(),
+								peer_frame.GetPeerLinkManagementElement(),
+								m_meshConfig
+								);
+						return;
+					case WifiMeshMultihopActionHeader::PEER_LINK_OPEN:
+						m_peerManager->SetOpenReceived(
+								GetAddress(),
+								peerAddress,
+								peer_frame.GetPeerLinkManagementElement(),
+								m_meshConfig
+								);
+						return;
+					case WifiMeshMultihopActionHeader::PEER_LINK_CLOSE:
+						m_peerManager->SetCloseReceived(
+								GetAddress(),
+								peerAddress,
+								peer_frame.GetPeerLinkManagementElement()
+								);
+						return;
+					default:
+						return;
+			}
+				break;
+				}
+			case WifiMeshMultihopActionHeader::MESH_PATH_SELECTION:
+			{
+				if(!m_peerManager->IsActiveLink(GetAddress(), hdr->GetAddr2()))
+					return;
+				switch(actionValue.pathSelection)
+				{
+					case WifiMeshMultihopActionHeader::PATH_REQUEST:
+						{
+						WifiPreqInformationElement preq;
+						packet->RemoveHeader(preq);
+						//TODO:recalculate
+						//metric
+						m_preqReceived(preq, hdr->GetAddr2(), CalculateMetric(hdr->GetAddr2()));
+						return;
+						}
+					case WifiMeshMultihopActionHeader::PATH_REPLY:
+						{
+						WifiPrepInformationElement prep;
+						packet->RemoveHeader(prep);
+						m_prepReceived(prep, hdr->GetAddr2(), CalculateMetric(hdr->GetAddr2()));
+						}
+						return;
+					case WifiMeshMultihopActionHeader::PATH_ERROR:
+						{
+						WifiPerrInformationElement perr;
+						packet->RemoveHeader(perr);
+						m_perrReceived(perr, hdr->GetAddr2());
+						}
+						return;
+					case WifiMeshMultihopActionHeader::ROOT_ANNOUNCEMENT:
+						return;
+				}
+			}
+			default:
+				break;
+		}
+	}
+	if(hdr->IsData())
+	{
+		NS_ASSERT((hdr->IsFromDs()) && (hdr->IsToDs()));
+		NS_ASSERT(hdr->GetAddr4()!=Mac48Address::GetBroadcast());
+		//check seqno
+		WifiMeshHeader meshHdr;
+		packet->RemoveHeader(meshHdr);
+		NS_LOG_DEBUG(
+				"DATA TA="<< hdr->GetAddr2()<<
+				", da="<<hdr->GetAddr3()<<
+				", sa="<<hdr->GetAddr4()<<
+				", TTL="<<(int)meshHdr.GetMeshTtl());
+		HwmpTag tag;
+		//mesh header is present within DATA and multihop action frames, so it must be done within MAC
+		tag.SetSeqno(meshHdr.GetMeshSeqno());
+		tag.SetAddress(hdr->GetAddr2());
+		tag.SetTtl(meshHdr.GetMeshTtl());
+		//metric should be later
+		packet->RemoveAllTags();
+		packet->AddTag(tag);
+	if(m_peerManager->IsActiveLink(GetAddress(), hdr->GetAddr2()))
+		ForwardUp(packet, hdr->GetAddr4(), hdr->GetAddr3());
+	}
+}
+
+Time
+MeshWifiMac::CalcSwDelay()
+{
+	UniformVariable coefficient(0.0, m_softwareDelay.GetSeconds());
+	Time delay = Seconds(coefficient.GetValue());
+	if(delay.GetSeconds() + Simulator::Now().GetSeconds() < m_lastMgtFrame.GetSeconds())
+		delay = Seconds(m_lastMgtFrame.GetSeconds() - Simulator::Now().GetSeconds());
+	m_lastMgtFrame = Seconds(Simulator::Now().GetSeconds()+delay.GetSeconds());
+	NS_ASSERT(delay.GetSeconds() >= 0);
+	return delay;
+}
+
+void
+MeshWifiMac::SendPeerLinkOpen(PeerLinkManagementElement peer_element, Mac48Address peerAddress)
+{
+	MeshMgtPeerLinkManFrame open;
+	open.SetOpen();
+	open.SetMeshConfigurationElement(m_meshConfig);
+	open.SetPeerLinkManagementElement(peer_element);
+	Simulator::Schedule(CalcSwDelay() ,&MeshWifiMac::QueuePeerLinkFrame, this, open, peerAddress);
+}
+
+void
+MeshWifiMac::SendPeerLinkConfirm(PeerLinkManagementElement peer_element, Mac48Address peerAddress, uint16_t aid)
+{	
+	MeshMgtPeerLinkManFrame confirm;
+	confirm.SetConfirm();
+	confirm.SetMeshConfigurationElement(m_meshConfig);
+	confirm.SetPeerLinkManagementElement(peer_element);
+	confirm.SetAid(aid);
+	Simulator::Schedule(CalcSwDelay() ,&MeshWifiMac::QueuePeerLinkFrame, this, confirm, peerAddress);
+
+}
+
+void
+MeshWifiMac::SendPeerLinkClose(PeerLinkManagementElement peer_element, Mac48Address peerAddress)
+{
+	MeshMgtPeerLinkManFrame close;
+	close.SetClose();
+	close.SetMeshConfigurationElement(m_meshConfig);
+	close.SetPeerLinkManagementElement(peer_element);
+	Simulator::Schedule(CalcSwDelay() ,&MeshWifiMac::QueuePeerLinkFrame, this, close, peerAddress);
+
+}
+
+void
+MeshWifiMac::PeerLinkStatus(Mac48Address peerAddress, bool status)
+{
+	//pass information to HwmpState
+	m_peerStatusCallback(peerAddress, status, CalculateMetric(peerAddress));
+}
+void
+MeshWifiMac::QueuePeerLinkFrame(MeshMgtPeerLinkManFrame peer_frame, Mac48Address peerAddress)
+{
+	Ptr<Packet> packet = Create<Packet> ();
+	//Setting peer frame:
+	peer_frame.SetSupportedRates(GetSupportedRates ());
+	peer_frame.SetQosField(0);
+	peer_frame.SetMeshId(GetSsid());
+	packet->AddHeader (peer_frame);
+	//multihop header:
+	WifiMeshMultihopActionHeader multihopHdr;
+	if(peer_frame.IsOpen())
+	{
+		WifiMeshMultihopActionHeader::ACTION_VALUE action;
+		action.peerLink = WifiMeshMultihopActionHeader::PEER_LINK_OPEN;
+		multihopHdr.SetAction(WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT, action);
+	}
+	if(peer_frame.IsConfirm())
+	{
+		WifiMeshMultihopActionHeader::ACTION_VALUE action;
+		action.peerLink = WifiMeshMultihopActionHeader::PEER_LINK_CONFIRM;
+		multihopHdr.SetAction(WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT, action);
+	}
+	if(peer_frame.IsClose())
+	{
+		WifiMeshMultihopActionHeader::ACTION_VALUE action;
+		action.peerLink = WifiMeshMultihopActionHeader::PEER_LINK_CLOSE;
+		multihopHdr.SetAction(WifiMeshMultihopActionHeader::MESH_PEER_LINK_MGT, action);
+	}
+	packet->AddHeader(multihopHdr);
+	//mesh header:
+	WifiMeshHeader meshHdr;
+	meshHdr.SetMeshTtl(1);
+	meshHdr.SetMeshSeqno(0);
+	packet->AddHeader(meshHdr);
+	//Wifi Mac header:
+	WifiMacHeader hdr;
+	hdr.SetMultihopAction();
+	hdr.SetAddr1 (peerAddress);
+	hdr.SetAddr2 (GetAddress ());
+	hdr.SetAddr3 (GetAddress ());
+	hdr.SetDsNotFrom ();
+	hdr.SetDsNotTo ();
+	//queue:
+	m_VO->Queue(packet,hdr);
+}
+
+void
+MeshWifiMac::SetSoftwareDelay(Time delay)
+{
+	m_softwareDelay = delay;
+}
+
+Time
+MeshWifiMac::GetSoftwareDelay()
+{
+	return m_softwareDelay;
+}
+
+void
+MeshWifiMac::SendPreq(const WifiPreqInformationElement& preq)
+{
+	//Add a PREQ
+	Ptr<Packet> packet = Create<Packet> ();
+	packet->AddHeader(preq);
+	//Add a Action values:
+	WifiMeshMultihopActionHeader multihopHdr;
+	WifiMeshMultihopActionHeader::ACTION_VALUE action;
+	action.pathSelection = WifiMeshMultihopActionHeader::PATH_REQUEST;
+	multihopHdr.SetAction(WifiMeshMultihopActionHeader::MESH_PATH_SELECTION, action);
+	packet->AddHeader(multihopHdr);
+	//Add a mesh Header
+	WifiMeshHeader meshHdr;
+	//TODO: normal seqno!
+	meshHdr.SetMeshTtl(1);
+	meshHdr.SetMeshSeqno(0);
+	packet->AddHeader(meshHdr);
+	//Add a wifi header:
+	WifiMacHeader hdr;
+	hdr.SetMultihopAction();
+	hdr.SetAddr1 (Mac48Address::GetBroadcast ());
+	hdr.SetAddr2 (GetAddress ());
+	hdr.SetAddr3 (Mac48Address("00:00:00:00:00:00"));
+	hdr.SetDsNotFrom ();
+	hdr.SetDsNotTo ();
+	Simulator::Schedule(CalcSwDelay() ,&MeshWifiMac::QueuePathSelectionFrame, this, packet, hdr);
+	//m_VO->Queue(packet,hdr);
+
+}
+
+void
+MeshWifiMac::SendPrep(const WifiPrepInformationElement& prep, const Mac48Address& to)
+{
+	if(!m_peerManager->IsActiveLink(GetAddress(), to))
+		return;
+	Ptr<Packet> packet = Create<Packet> ();
+	packet->AddHeader(prep);
+	//Add a Action values:
+	WifiMeshMultihopActionHeader multihopHdr;
+	WifiMeshMultihopActionHeader::ACTION_VALUE action;
+	action.pathSelection = WifiMeshMultihopActionHeader::PATH_REPLY;
+	multihopHdr.SetAction(WifiMeshMultihopActionHeader::MESH_PATH_SELECTION, action);
+	packet->AddHeader(multihopHdr);
+	//Add a mesh Header
+	WifiMeshHeader meshHdr;
+	//TODO: normal seqno!
+	meshHdr.SetMeshTtl(1);
+	meshHdr.SetMeshSeqno(0);
+	packet->AddHeader(meshHdr);
+	//Add a wifi header:
+	WifiMacHeader hdr;
+	hdr.SetMultihopAction();
+	hdr.SetDsNotTo();
+	hdr.SetDsNotFrom();
+	hdr.SetAddr1(to);
+	hdr.SetAddr2(GetAddress());
+	hdr.SetAddr3(Mac48Address("00:00:00:00:00:00"));
+	//m_VO->Queue(packet,hdr);
+	Simulator::Schedule(CalcSwDelay() ,&MeshWifiMac::QueuePathSelectionFrame, this, packet, hdr);
+}
+
+void
+MeshWifiMac::SendPerr(const WifiPerrInformationElement& perr, std::vector<Mac48Address> receivers)
+{
+	NS_ASSERT(receivers.size()!=0);
+	Ptr<Packet> packet = Create<Packet> ();
+	packet->AddHeader(perr);
+	//Add a Action values:
+	WifiMeshMultihopActionHeader multihopHdr;
+	WifiMeshMultihopActionHeader::ACTION_VALUE action;
+	action.pathSelection = WifiMeshMultihopActionHeader::PATH_ERROR;
+	multihopHdr.SetAction(WifiMeshMultihopActionHeader::MESH_PATH_SELECTION, action);
+	packet->AddHeader(multihopHdr);
+	//Add a mesh Header
+	WifiMeshHeader meshHdr;
+	//TODO: normal seqno!
+	meshHdr.SetMeshTtl(1);
+	meshHdr.SetMeshSeqno(0);
+	packet->AddHeader(meshHdr);
+	//Add a wifi header:
+	WifiMacHeader hdr;
+	hdr.SetMultihopAction();
+	hdr.SetDsNotTo();
+	hdr.SetDsNotFrom();
+	hdr.SetAddr2(GetAddress());
+	hdr.SetAddr3(Mac48Address("00:00:00:00:00:00"));
+	//m_VO->Queue(packet,hdr);
+	for(unsigned int i = 0; i < receivers.size(); i ++)
+	{
+		NS_LOG_DEBUG(GetAddress()<<" is sending PERR to "<<receivers[i]);
+		hdr.SetAddr1(receivers[i]);
+		Simulator::Schedule(CalcSwDelay() ,&MeshWifiMac::QueuePathSelectionFrame, this, packet, hdr);
+	}
+}
+void
+MeshWifiMac::QueuePathSelectionFrame(Ptr<Packet> packet, const WifiMacHeader hdr)
+{
+	m_VO->Queue(packet, hdr);
+}
+void
+MeshWifiMac::SetPreqReceivedCallback(
+		Callback<void, WifiPreqInformationElement&, const Mac48Address&, const uint32_t&> cb)
+{
+	m_preqReceived = cb;
+}
+
+void
+MeshWifiMac::SetPrepReceivedCallback(
+		Callback<void, WifiPrepInformationElement&, const Mac48Address&, const uint32_t&> cb)
+{
+	m_prepReceived = cb;
+}
+
+void
+MeshWifiMac::SetPerrReceivedCallback(
+		Callback<void, WifiPerrInformationElement&, const Mac48Address&> cb)
+{
+	m_perrReceived = cb;
+}
+
+void
+MeshWifiMac::SetPeerStatusCallback(
+		Callback<void, Mac48Address, bool, uint32_t> cb)
+{
+	m_peerStatusCallback = cb;
+}
+
+uint32_t
+MeshWifiMac::CalculateMetric(Mac48Address peerAddress)
+{
+	//suppose Bt == 1000 bytes;
+	uint32_t testLength = 1000;
+	WifiRemoteStation *peerSta = m_stationManager->Lookup (peerAddress);
+	WifiTxStatistics::RATE_LENGTH_STAT stats = peerSta->GetTxStat().statistics;
+	Time overhead = m_sifs  + MicroSeconds(32) + MicroSeconds(8);
+	uint32_t metric = (uint32_t)((double)overhead.GetNanoSeconds()/102.4);
+	uint32_t maxRate = 0;
+	uint32_t packet_sent = 0;
+	for(WifiTxStatistics::RATE_LENGTH_STAT::iterator lengthPos = stats.begin(); lengthPos !=stats.end(); lengthPos++)
+	{
+		if(lengthPos->first > testLength)
+			continue;
+		for(
+				WifiTxStatistics::RATE_STAT::iterator ratePos = lengthPos->second.begin();
+				ratePos != lengthPos->second.end();
+				ratePos ++
+				)
+		{
+#if 0
+			NS_LOG_DEBUG("Rate is "<<ratePos->first
+					<<": SUCCESS = "<<ratePos->second.packetsAcked
+					<<", RRETRY = " <<ratePos->second.packetsRetried
+					<<", FAILURE = "<<ratePos->second.packetsFailed);
+#endif
+			double coefficient = 
+				(double)(
+						ratePos->second.packetsRetried
+						+ ratePos->second.packetsAcked
+					)/((double)ratePos->second.packetsAcked);
+			uint16_t avgLength = 0;
+			if(ratePos->second.packetsAcked == 0)
+				avgLength = lengthPos->first;
+			else
+				avgLength = ratePos->second.bytesAcked/ratePos->second.packetsAcked;
+			uint32_t payload = (uint32_t)((double)avgLength / ((double)ratePos->first)*1e9);
+			if(packet_sent < ratePos->second.packetsAcked)
+			{
+				metric = (uint32_t)(coefficient*((double)overhead.GetNanoSeconds() + (double)payload)/10240);
+				packet_sent = ratePos->second.packetsAcked;
+				maxRate = ratePos->first;
+			}
+		}
+	}
+
+	//NS_LOG_DEBUG("RATE is "<<maxRate<<" metric is "<<metric);
+	//peerSta->ResetTxStat();
+	NS_ASSERT(metric !=0);
+	return metric;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-mac.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,399 @@
+/* -*-  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>
+ *          Evgeny Khorov <horov@frtk.ru>
+ */
+
+
+#ifndef MAC_HIGH_MESH_H
+#define MAC_HIGH_MESH_H
+
+#include <stdint.h>
+#include <map>
+#include "ns3/mac48-address.h"
+#include "mgt-headers.h"
+#include "mesh-mgt-headers.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+#include "mesh-wifi-beacon-timing-element.h"
+#include "wifi-remote-station-manager.h"
+#include "mesh-wifi-peer-manager.h"
+#include "wifi-mac.h"
+
+namespace ns3 {
+
+	class WifiMacHeader;
+	class DcaTxop;
+	class WifiPhy;
+	class DcfManager;
+	class MacRxMiddle;
+	class MacLow;
+	class WifiPeerManager;
+	/**
+	 * \brief Implements MAC-layer of mesh point: beaconing and
+	 * peer link management.
+	 *
+	 * \details Handles sending and receiving beacons. Tells all
+	 * needed information about beacons to MeshWifiPeerManager class, which
+	 * handles peer link management state machine. Asks
+	 * WifiPeerManager wether
+	 * receive or discard frame obtained from neighbour.
+	 * Now only three output queues are used: 
+	 * one for beacons (PIFS and no backoff),
+	 * one for background traffic,
+	 * one for management and priority traffic.
+	 */
+	class MeshWifiMac : public WifiMac
+	{
+		public:
+			static TypeId		GetTypeId (void);
+
+			MeshWifiMac ();
+			~MeshWifiMac ();
+			// 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 (void) const;
+			virtual Time		GetSifs (void) const;
+			virtual Time		GetPifs (void) const;
+  			virtual Time		GetCtsTimeout (void) const;
+  			virtual Time		GetAckTimeout (void) const;
+			virtual Time		GetEifsNoDifs (void) 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 (void) 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 (void) const;
+			virtual Mac48Address	GetBssid (void) const;
+			virtual Ssid		GetSsid (void) const;
+			virtual void		SetAddress (Mac48Address address);
+			virtual void		SetSsid (Ssid ssid);
+			/**
+			 * \param interval is an interval between two
+			 * successive beacons
+			 */
+			void			SetBeaconInterval (Time interval);
+			/**
+			 * \returns interval between two beacons
+			 */
+			Time			GetBeaconInterval (void) const;
+			/**
+			 * \param delay is the maximum software delay.
+			 *
+			 * \details Software delay is calculated as uniformely
+			 * distributed random value between zero and
+			 * given parameter.
+			 *
+			 * All management frames are sent after software delay is passed,
+			 * for example, beacon is formed at software
+			 * delay before putting it to the queue.
+			 *
+			 * \attention The software delay is supposed
+			 * to be independent from traffic intensity.
+			 *
+			 */
+			void			SetSoftwareDelay(Time delay);
+			/**
+			 * \returns software delay parameter
+			 */
+			Time			GetSoftwareDelay();
+			/**
+			 * \param manager is pointer to the
+			 * WifiPeerManager class, which implements
+			 * peer-link management state machine.
+			 *
+			 * \details The purpose of peer manager is
+			 * obtaining all needed information from
+			 * beacons and send peer link management
+			 * frames.
+			 *
+			 * This funcion sets all needed callbacks to
+			 * a given peer manager
+			 */
+                        void                    SetPeerLinkManager(Ptr<WifiPeerManager> manager);
+			virtual void		SetPreqReceivedCallback(
+					Callback<void, WifiPreqInformationElement&, const Mac48Address&, const uint32_t&> cb);
+			/**
+			 * \brief this callback is set by Hwmp routing
+			 * protocol and executed when MAC has received
+			 * PREP.
+			 * \param cb is a callback to be executed when
+			 * receiving PREP.
+			 */
+			virtual void		SetPrepReceivedCallback(
+					Callback<void, WifiPrepInformationElement&, const Mac48Address&, const uint32_t&> cb);
+			/**
+			 * \brief this callback is set by Hwmp routing
+			 * protocol and executed when MAC has received
+			 * PERR.
+			 * \param cb is a callback to be executed when
+			 * receiving PERR.
+			 */
+			virtual void		SetPerrReceivedCallback(
+					Callback<void, WifiPerrInformationElement&, const Mac48Address&> cb);
+
+			/**
+			 * \brief this callback is set by Hwmp routing
+			 * protocol and executed when MAC has detected
+			 * the peer link failure
+			 * \param cb is a callback to be executed when
+			 * peer failure has ben detected
+			 */
+			virtual void            SetPeerStatusCallback(
+					Callback<void, Mac48Address, bool, uint32_t> cb);
+			/**
+			 * \brief Sends a PREQ frame.
+			 * \param preq is preq information element
+			 * formed by protocol. This function just adds
+			 * a proper WifiMacHeader
+			 * \attention This method is public, because
+			 * HWMP makes a callback using this method
+			 */
+			virtual void		SendPreq(const WifiPreqInformationElement& preq);
+			/**
+			 * \brief Sends a PREP frame.
+			 * \param prep is prep information element
+			 * formed by protocol. This function just adds
+			 * a proper WifiMacHeader
+			 * \param to is an address of retransmitter of
+			 * the prep
+			 * \attention This method is public, because
+			 * HWMP makes a callback using this method
+			 */
+
+			virtual void		SendPrep(const WifiPrepInformationElement& prep, const Mac48Address& to);
+			/**
+			 * \brief Sends a PERR frame.
+			 * \param perr is perr information element
+			 * formed by protocol. This function just adds
+			 * a proper WifiMacHeader.
+			 * \param receivers is list of addresses where
+			 * to send PERR (unicast PERR case)
+			 * \attention This method is public, because
+			 * HWMP makes a callback using this method
+			 */
+			virtual void		SendPerr(const WifiPerrInformationElement& perr, std::vector<Mac48Address> receivers);
+			/**
+			 * \brief Sends PeerLinkOpen frame to a given
+			 * address. Mac only forms a proper
+			 * WifiMacHeader.
+			 * \param peer_element is peer link frame to
+			 * be sent
+			 * \param peerAddress is the address of
+			 * destination of given frame
+			 */
+			void			SendPeerLinkOpen(
+					PeerLinkManagementElement peer_element,
+					Mac48Address peerAddress
+					);
+			/**
+			 * \brief Sends PeerLinkConfirm frame to a given
+			 * address. Mac only forms a proper
+			 * WifiMacHeader.
+			 * \param peer_element is peer link frame to
+			 * be sent
+			 * \param peerAddress is the address of
+			 * destination of given frame
+			 * \param aid is the assocciation ID stored in
+			 * peer manager
+			 */
+			void			SendPeerLinkConfirm(
+					PeerLinkManagementElement peer_element,
+					Mac48Address peerAddress,
+					uint16_t aid
+					);
+			/**
+			 * \brief Sends PeerLinkClose frame to a given
+			 * address. Mac only forms a proper
+			 * WifiMacHeader.
+			 * \param peer_element is peer link frame to
+			 * be sent
+			 * \param peerAddress is the address of
+			 * destination of given frame
+			 */
+			void			SendPeerLinkClose(
+					PeerLinkManagementElement peer_element,
+					Mac48Address peerAddress
+					);
+			/**
+			 * \brief this method is executed by peer
+			 * manager when peer link opened or closed
+			 * \param status true when link was opened,
+			 * false if link was closed
+			 * \param peerAddress is the address of
+			 * destination of given frame
+			 */
+			virtual void		PeerLinkStatus(Mac48Address peerAddress, bool status);
+
+			/**
+			 * \brief Peer Manager notifyes MAC about new
+			 * peer link or peer link failure.
+			 * \details This method should pass this event
+			 * to HWMP, and it should generate new routing
+			 * information or should generate Path Error
+			 * \param peerAddress it the address of
+			 * neighbour
+			 * \param status If true - new peer link, perr
+			 * link failure otherwise
+			 */
+			void			PeerEvent(
+					Mac48Address	peerAddress,
+					bool		status
+					);
+		private:
+			void		Receive (Ptr<Packet> packet, WifiMacHeader const *hdr);
+			virtual void	ForwardUp (Ptr<Packet> packet, Mac48Address src, Mac48Address dst);
+			void		ForwardDown(
+					Ptr<const Packet> packet,
+					Mac48Address from,
+					Mac48Address to
+					);
+			void		TxOk (WifiMacHeader const &hdr);
+			void		TxFailed (WifiMacHeader const &hdr);
+			/**
+			 * \brief At the software delay before TBTT
+			 * SendOneBeacon is ececuted. It forms a
+			 * beacon frame body. Then calculates software
+			 * delay and schedules QueueOneBeacon
+			 */
+			void		SendOneBeacon (void);
+			/**
+			 * \brief Puts a formed beacon to the output
+			 * queue. SendOneBeacon forms a beacon and
+			 * after software delay QueueOneBeacon is
+			 * executed
+			 * \param beacon_hdr is beacon to be queued
+			 */
+			void		QueueOneBeacon (MgtMeshBeaconHeader beacon_hdr);
+			/**
+			 * \brief Executed after software delay by
+			 * SendPeerLinkOpen/Confirm/Close frames and
+			 * puts this frame to the output queue.
+			 * \param peer_frame peer link management
+			 * frame
+			 * \param peerAddress the address of
+			 * destination.
+			 */
+			void		QueuePeerLinkFrame(MeshMgtPeerLinkManFrame peer_frame, Mac48Address peerAddress);
+			/**
+			 * \brief Executed after software delay by
+			 * SendPreq/Prep/Perr frames and
+			 * puts this frame to the output queue.
+			 * \param packet is packet body,
+			 * \param hdr is WifiMacHeader
+			 */
+			void		QueuePathSelectionFrame(Ptr<Packet> packet, const WifiMacHeader hdr);
+			void		SetBeaconGeneration (bool enable);
+			bool		GetBeaconGeneration (void) const;
+			SupportedRates	GetSupportedRates (void) const;
+			virtual void	DoDispose (void);
+
+			Ptr<DcaTxop>			m_BE;
+			Ptr<DcaTxop>			m_BK;
+			Ptr<DcaTxop>			m_VI;
+			Ptr<DcaTxop>			m_VO;
+			Ptr<DcaTxop>			m_beaconDca;
+			Ptr<WifiRemoteStationManager>	m_stationManager;
+			Ptr<WifiPhy>			m_phy;
+			Callback<void,Ptr<Packet>, Mac48Address, Mac48Address>
+							m_upCallback;
+			Time				m_beaconInterval;
+			Time				m_randomStart;
+
+			DcfManager *			m_dcfManager;
+			MacRxMiddle *			m_rxMiddle;
+			Ptr<MacLow>			m_low;
+			Mac48Address			m_address;
+			Ssid				m_MeshId;
+			EventId				m_beaconFormEvent;
+			EventId				m_beaconSendEvent;
+			Time				m_slot;
+			Time				m_sifs;
+  			Time				m_pifs;
+			Time				m_ackTimeout;
+			Time				m_ctsTimeout;
+
+			Time				m_eifsNoDifs;
+			MeshConfigurationElement	m_meshConfig; //Stores my configuration;
+			//Peer Descriptor pointer:
+			Ptr<WifiPeerManager> 		m_peerManager;
+			Time				m_softwareDelay;
+			/**
+			 * \attention Software delay is used for management
+			 * frames, so, if this delay is calculated
+			 * independenly, the packet order may be
+			 * broken, so the last mgt frame sending time
+			 * should be keeped within MAC
+			 */
+			Time				m_lastMgtFrame;
+			/**
+			 * \returns the value of software delay
+			 * uniformely distributed between 0 and
+			 * m_softwareDealy (initiated by
+			 * SetSoftwareDelay method).
+			 */
+			Time				CalcSwDelay();
+			/**
+			 * \brief keeps delay for sending first
+			 * beacon. this delay is uniformely
+			 * distributed between 0 and given value
+			 */
+			Time				m_beaconFormingRandomDelay;
+			Callback<void, WifiPreqInformationElement&, const Mac48Address&, const uint32_t&>
+							m_preqReceived;
+			Callback<void, WifiPrepInformationElement&, const Mac48Address&, const uint32_t&>
+							m_prepReceived;
+			Callback<void, WifiPerrInformationElement&, const Mac48Address&>
+							m_perrReceived;
+			Callback<void, Mac48Address, bool, uint32_t>
+							m_peerStatusCallback;
+			/**
+			 * \brief metric calculation parameters
+			 */
+			uint32_t			CalculateMetric(Mac48Address peerAddress);
+			struct addrcmp
+			{
+				bool operator()(const Mac48Address addr1, Mac48Address addr2) const
+				{
+					uint8_t s1[6], s2[6];
+					addr1.CopyTo(s1);
+					addr2.CopyTo(s2);
+					for(int i = 0; i < 6; i ++)
+						if(s1[i] > s2[i])
+							return true;
+					return false;
+				}
+			};
+
+			std::map<Mac48Address, uint32_t, addrcmp>
+							m_metricDatabase;
+	};
+
+} // namespace ns3
+
+
+#endif /* MAC_HIGH_MESH_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-peer-manager.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,987 @@
+/* -*-  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>
+ *          Ivan Pustogarov <chinsa1@rambler.ru>
+ *          Evgeny Khorov <horov@frtk.ru>
+ */
+
+
+#include "mesh-wifi-peer-manager.h"
+#include "dot11s-parameters.h"
+#include "ns3/simulator.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/random-variable.h"
+NS_LOG_COMPONENT_DEFINE ("WifiPeerManager");
+namespace ns3 {
+/***************************************************
+ *	PeerLinkDescriptor
+ ***************************************************/
+WifiPeerLinkDescriptor::WifiPeerLinkDescriptor():
+	m_localLinkId(0),
+	m_peerLinkId(0),
+	m_state(IDLE),
+	m_retryCounter(0),
+	m_maxBeaconLoss(3)
+{}
+
+	void
+WifiPeerLinkDescriptor::SetPeerAddress(Mac48Address macaddr)
+{
+	m_peerAddress = macaddr;
+}
+
+	void
+WifiPeerLinkDescriptor::SetLocalAddress(Mac48Address macaddr)
+{
+	m_localAddress = macaddr;
+}
+
+	void
+WifiPeerLinkDescriptor::SetLocalLinkId(uint16_t id)
+{
+	m_localLinkId = id;
+}
+	void
+WifiPeerLinkDescriptor::SetLocalAid(uint16_t aid)
+{
+	m_assocId = aid;
+}
+	void
+WifiPeerLinkDescriptor::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, &WifiPeerLinkDescriptor::BeaconLoss, this);
+}
+
+	void
+WifiPeerLinkDescriptor::SetMaxBeaconLoss(uint8_t maxBeaconLoss)
+{
+	m_maxBeaconLoss = maxBeaconLoss;
+}
+
+	void
+WifiPeerLinkDescriptor::SetLinkStatusCallback(Callback<void, Mac48Address, Mac48Address, bool> cb)
+{
+	m_linkStatusCallback = cb;
+}
+	void
+WifiPeerLinkDescriptor::BeaconLoss()
+{
+	StateMachine(CNCL);
+}
+
+	void
+WifiPeerLinkDescriptor::SetBeaconTimingElement(WifiBeaconTimingElement beaconTiming)
+{
+	m_beaconTiming = beaconTiming;
+}
+
+Mac48Address
+WifiPeerLinkDescriptor::GetPeerAddress() const
+{
+	return m_peerAddress;
+}
+
+Mac48Address
+WifiPeerLinkDescriptor::GetLocalAddress() const
+{
+	return m_localAddress;
+}
+
+
+uint16_t
+WifiPeerLinkDescriptor::GetLocalAid()const
+{
+	return m_assocId;
+}
+
+Time
+WifiPeerLinkDescriptor::GetLastBeacon() const
+{
+	return m_lastBeacon;
+}
+
+Time
+WifiPeerLinkDescriptor::GetBeaconInterval() const
+{
+	return m_beaconInterval;
+}
+WifiBeaconTimingElement
+WifiPeerLinkDescriptor::GetBeaconTimingElement() const
+{
+	return m_beaconTiming;
+}
+
+	void
+WifiPeerLinkDescriptor::ClearTimingElement()
+{
+	m_beaconTiming.ClearTimingElement();
+}
+
+
+void  WifiPeerLinkDescriptor::MLMECancelPeerLink(dot11sReasonCode reason)
+{
+	StateMachine(CNCL,reason);
+}
+
+void  WifiPeerLinkDescriptor::MLMEPassivePeerLinkOpen()
+{
+	StateMachine(PASOPN);
+}
+
+void  WifiPeerLinkDescriptor::MLMEActivePeerLinkOpen()
+{
+	StateMachine(ACTOPN);
+}
+void WifiPeerLinkDescriptor::MLMEPeeringRequestReject()
+{
+	StateMachine(REQ_RJCT, PEER_LINK_CANCELLED);
+}
+#if 0
+void  WifiPeerLinkDescriptor::MLMEBindSecurityAssociation()
+{
+	StateMachine(BNDSA);
+}
+#endif
+	void
+WifiPeerLinkDescriptor::SetMac(Ptr<MeshWifiMac> mac)
+{
+	m_mac = mac;
+}
+void WifiPeerLinkDescriptor::PeerLinkClose(uint16_t localLinkId,uint16_t peerLinkId, dot11sReasonCode 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 WifiPeerLinkDescriptor::PeerLinkOpenAccept(uint16_t localLinkId, MeshConfigurationElement  conf)
+{
+	if( m_peerLinkId == 0)
+		m_peerLinkId = localLinkId;
+	m_configuration = conf;
+	StateMachine(OPN_ACPT);
+}
+
+void WifiPeerLinkDescriptor::PeerLinkOpenReject(uint16_t localLinkId, MeshConfigurationElement  conf,dot11sReasonCode reason)
+{
+	if( m_peerLinkId == 0)
+		m_peerLinkId = localLinkId;
+	m_configuration = conf; 
+	StateMachine(OPN_RJCT,reason);
+}
+
+	void
+WifiPeerLinkDescriptor::PeerLinkConfirmAccept(uint16_t localLinkId,uint16_t peerLinkId, uint16_t peerAid, MeshConfigurationElement  conf)
+{
+	if( m_localLinkId != peerLinkId)
+		return;
+	if( m_peerLinkId == 0)
+		m_peerLinkId = localLinkId;
+	else if ( m_peerLinkId != localLinkId )
+		return;
+	m_configuration = conf;
+	m_peerAssocId = peerAid;
+	StateMachine(CNF_ACPT);
+}
+
+void   WifiPeerLinkDescriptor:: PeerLinkConfirmReject(uint16_t localLinkId, uint16_t peerLinkId, 
+		MeshConfigurationElement  conf,dot11sReasonCode reason)
+{
+	if( m_localLinkId != peerLinkId)
+		return;
+	if( m_peerLinkId == 0)
+		m_peerLinkId = localLinkId;
+	else if ( m_peerLinkId != localLinkId )
+		return;
+	m_configuration = conf;
+	StateMachine(CNF_RJCT,reason);
+}
+
+bool
+WifiPeerLinkDescriptor::LinkIsEstab() const
+{
+	if(m_state == ESTAB)
+		return true;
+	return false;
+}
+
+bool
+WifiPeerLinkDescriptor::LinkIsIdle() const
+{
+	if(m_state == IDLE)
+		return true;
+	return false;
+}
+
+	void
+WifiPeerLinkDescriptor::StateMachine(PeerEvent event,dot11sReasonCode reasoncode)
+{
+	switch(m_state)
+	{
+		case IDLE:
+			switch(event)
+			{
+				case PASOPN:
+					m_state = LISTEN;
+					break;
+				case ACTOPN:
+					m_state = OPN_SNT;
+					SendPeerLinkOpen();
+					SetRetryTimer();
+					break;
+				default:{}
+			}
+			break;
+		case LISTEN:
+			switch(event)
+			{
+				case CNCL:
+				case CLS_ACPT:
+					m_state=IDLE;
+					// TODO Callback MLME-SignalPeerLinkStatus
+					break;
+				case REQ_RJCT:
+					SendPeerLinkClose(reasoncode);
+					break;
+				case ACTOPN:
+					m_state=OPN_SNT;
+					SendPeerLinkOpen();
+					SetRetryTimer();
+					break;
+				case OPN_ACPT:
+					m_state = OPN_RCVD;
+					SendPeerLinkConfirm();
+					SendPeerLinkOpen();
+					SetRetryTimer();
+					break;
+				default:{}
+			}
+			break;
+		case OPN_SNT:
+			switch(event)
+			{
+				case TOR1:
+					SendPeerLinkOpen();
+					m_retryCounter++;
+					SetRetryTimer();
+					break;
+				case CNF_ACPT:
+					m_state = CNF_RCVD;
+					ClearRetryTimer();
+					SetConfirmTimer();
+					break;
+				case OPN_ACPT:
+					m_state = OPN_RCVD;
+					SendPeerLinkConfirm();
+					break;
+				case CLS_ACPT:
+					m_state = HOLDING;
+					ClearRetryTimer();
+					SendPeerLinkClose(MESH_CLOSE_RCVD);
+					SetHoldingTimer();
+					break;
+				case OPN_RJCT:
+				case CNF_RJCT:
+					m_state = HOLDING;
+					ClearRetryTimer();
+					SendPeerLinkClose(reasoncode);
+					SetHoldingTimer();
+					break;
+				case TOR2:
+					m_state = HOLDING;
+					ClearRetryTimer();
+					SendPeerLinkClose(MESH_MAX_RETRIES);
+					SetHoldingTimer();
+					break;
+				case CNCL:
+					m_state = HOLDING;
+					ClearRetryTimer();
+					SendPeerLinkClose(PEER_LINK_CANCELLED);
+					SetHoldingTimer();
+					break;
+				default:{}
+			}
+			break;
+		case CNF_RCVD:
+			switch(event)
+			{
+				case CNF_ACPT:
+					break;
+				case OPN_ACPT:
+					m_state = ESTAB;
+NS_LOG_DEBUG("I am "<<m_localAddress<<", established link with "<<m_peerAddress<<", at "<<Simulator::Now());
+					ClearConfirmTimer();
+					SendPeerLinkConfirm();
+					m_linkStatusCallback(m_localAddress, m_peerAddress, true);
+					// TODO Callback MLME-SignalPeerLinkStatus
+					break;
+				case CLS_ACPT:
+					m_state = HOLDING;
+					ClearConfirmTimer();
+					SendPeerLinkClose(MESH_CLOSE_RCVD);
+					SetHoldingTimer();
+					break;
+				case CNF_RJCT:
+				case OPN_RJCT:
+					m_state = HOLDING;
+					ClearConfirmTimer();
+					SendPeerLinkClose(reasoncode);
+					SetHoldingTimer();
+					break;
+				case CNCL:
+					m_state = HOLDING;
+					ClearConfirmTimer();
+					SendPeerLinkClose(PEER_LINK_CANCELLED);
+					SetHoldingTimer();
+					break;
+				case TOC:
+					m_state = HOLDING;
+					SendPeerLinkClose(MESH_CONFIRM_TIMEOUT);
+					SetHoldingTimer();
+					break;
+				default:{}
+			}
+			break;
+		case OPN_RCVD:
+			switch(event)
+			{
+				case TOR1:
+					SendPeerLinkOpen();
+					m_retryCounter++;
+					SetRetryTimer();
+					break;
+				case CNF_ACPT:
+NS_LOG_DEBUG("I am "<<m_localAddress<<", established link with "<<m_peerAddress<<", at "<<Simulator::Now());
+					m_state = ESTAB;
+					ClearRetryTimer();
+					m_linkStatusCallback(m_localAddress, m_peerAddress, true);
+					// TODO Callback MLME-SignalPeerLinkStatus
+					break;
+				case CLS_ACPT:
+					m_state = HOLDING;
+					ClearRetryTimer();
+					SendPeerLinkClose(MESH_CLOSE_RCVD);
+					SetHoldingTimer();
+					break;
+				case OPN_RJCT:
+				case CNF_RJCT:
+					m_state = HOLDING;
+					ClearRetryTimer();
+					SendPeerLinkClose(reasoncode);
+					SetHoldingTimer();
+					break;
+				case TOR2:
+					m_state = HOLDING;
+					ClearRetryTimer();
+					SendPeerLinkClose(MESH_MAX_RETRIES);
+					SetHoldingTimer();
+					break;
+				case CNCL:
+					m_state = HOLDING;
+					ClearRetryTimer();
+					SendPeerLinkClose(PEER_LINK_CANCELLED);
+					SetHoldingTimer();
+					break;
+				default:{}
+			}
+			break;
+		case ESTAB:
+			switch(event)
+			{
+#if 0
+				case BNDSA:
+					m_state = ESTAB;
+					// TODO Callback MLME-SignalPeerLinkStatus
+					// TODO
+					break;
+#endif
+				case OPN_ACPT:
+					SendPeerLinkConfirm();
+					break;
+				case CLS_ACPT:
+NS_LOG_DEBUG("I am "<<m_localAddress<<", CLOSED link with "<<m_peerAddress<<", at "<<Simulator::Now()<<" Close received");
+					m_state = HOLDING;
+					SendPeerLinkClose(MESH_CLOSE_RCVD);
+					SetHoldingTimer();
+					m_linkStatusCallback(m_localAddress, m_peerAddress, false);
+					break;
+				case OPN_RJCT:
+				case CNF_RJCT:
+NS_LOG_DEBUG("I am "<<m_localAddress<<", CLOSED link with "<<m_peerAddress<<", at "<<Simulator::Now()<<" Rejected open or confirm");
+					m_state = HOLDING;
+					ClearRetryTimer();
+					SendPeerLinkClose(reasoncode);
+					SetHoldingTimer();
+					m_linkStatusCallback(m_localAddress, m_peerAddress, false);
+					break;
+				case CNCL:
+NS_LOG_DEBUG("I am "<<m_localAddress<<", CLOSED link with "<<m_peerAddress<<", at "<<Simulator::Now()<<" Link cancelled");
+					m_state = HOLDING;
+					SendPeerLinkClose(PEER_LINK_CANCELLED);
+					SetHoldingTimer();
+					m_linkStatusCallback(m_localAddress, m_peerAddress, false);
+					break;
+				default:{}
+			}
+			break;
+		case HOLDING:
+			switch(event)
+			{
+				case CLS_ACPT:
+					ClearHoldingTimer();
+				case TOH:
+					m_state = IDLE;
+					// TODO Callback MLME-SignalPeerLinkStatus
+					break;
+				case OPN_ACPT:
+				case CNF_ACPT:
+					m_state = HOLDING;
+					// reason not spec in D2.0
+					SendPeerLinkClose(PEER_LINK_CANCELLED);
+					break;
+				case OPN_RJCT:
+				case CNF_RJCT:
+					m_state = HOLDING;
+					SendPeerLinkClose(reasoncode);
+					break;
+				default:{}
+			}
+			break;
+	}
+}
+
+void WifiPeerLinkDescriptor::ClearRetryTimer()
+{
+	m_retryTimer.Cancel(); 
+}
+
+void WifiPeerLinkDescriptor::ClearConfirmTimer()
+{
+	m_confirmTimer.Cancel(); 
+}
+
+void WifiPeerLinkDescriptor::ClearHoldingTimer()
+{
+	m_holdingTimer.Cancel(); 
+}
+
+void WifiPeerLinkDescriptor::SendPeerLinkClose(dot11sReasonCode reasoncode)
+{
+	PeerLinkManagementElement peerElement;
+	peerElement.SetPeerClose(m_localLinkId, m_peerLinkId, reasoncode);
+	m_mac->SendPeerLinkClose(peerElement,m_peerAddress);
+}
+
+void WifiPeerLinkDescriptor::SendPeerLinkOpen()
+{
+	PeerLinkManagementElement peerElement;
+	peerElement.SetPeerOpen(m_localLinkId);
+	NS_ASSERT(m_mac!=NULL);
+	m_mac->SendPeerLinkOpen(peerElement,m_peerAddress);
+}
+
+void WifiPeerLinkDescriptor::SendPeerLinkConfirm()
+{
+	PeerLinkManagementElement peerElement;
+	peerElement.SetPeerConfirm(m_localLinkId, m_peerLinkId);
+	m_mac->SendPeerLinkConfirm(peerElement,m_peerAddress, m_assocId);
+}
+
+void WifiPeerLinkDescriptor::SetHoldingTimer()
+{
+	m_holdingTimer = Simulator::Schedule(dot11sParameters::dot11MeshHoldingTimeout,&WifiPeerLinkDescriptor::HoldingTimeout,this); 
+}
+
+void WifiPeerLinkDescriptor::HoldingTimeout()
+{
+	StateMachine(TOH); 
+}
+
+void WifiPeerLinkDescriptor::SetRetryTimer()
+{
+	m_retryTimer = Simulator::Schedule(dot11sParameters::dot11MeshRetryTimeout,&WifiPeerLinkDescriptor::RetryTimeout,this); 
+}
+
+void WifiPeerLinkDescriptor::RetryTimeout()
+{
+	if( m_retryCounter < dot11sParameters::dot11MeshMaxRetries)
+		StateMachine(TOR1);
+	else 
+		StateMachine(TOR2);
+}
+
+void WifiPeerLinkDescriptor::SetConfirmTimer()
+{
+	m_confirmTimer = Simulator::Schedule(dot11sParameters::dot11MeshConfirmTimeout,&WifiPeerLinkDescriptor::ConfirmTimeout,this); 
+}
+
+void WifiPeerLinkDescriptor::ConfirmTimeout()
+{
+	StateMachine(TOC); 
+}
+
+
+/***************************************************
+ *	PeerManager
+ ***************************************************/
+NS_OBJECT_ENSURE_REGISTERED (WifiPeerManager);
+
+	TypeId
+WifiPeerManager::GetTypeId (void)
+{
+	static TypeId tid = TypeId ("ns3::WifiPeerManager")
+		.SetParent<Object> ()
+		.AddConstructor<WifiPeerManager> ()
+		//peerLinkCleanupTimeout. This constant is not specified in Draft 2.0
+		.AddAttribute ("PeerLinkCleanupPeriod",
+				"PeerLinkCleanupPeriod",
+				TimeValue (MilliSeconds (80)),
+				MakeTimeAccessor (&WifiPeerManager::m_peerLinkCleanupPeriod),
+				MakeTimeChecker ()
+			      )
+		//MaxBeaconLost. This constant is not specified in Draft 2.0
+		.AddAttribute ("MaxBeaconLost", "Max Beacon Lost",
+				UintegerValue (3),
+				MakeUintegerAccessor (&WifiPeerManager::m_maxBeaconLoss),
+				MakeUintegerChecker<uint8_t> ()
+			      )
+		//maximum number of peer links.
+		.AddAttribute ("MaxNumberOfPeerLinks",
+				"Maximum number of peer links ",
+				UintegerValue (32),
+				MakeUintegerAccessor (&WifiPeerManager::m_maxNumberOfPeerLinks),
+				MakeUintegerChecker<uint8_t> ()
+			      );
+	return tid;
+
+}
+WifiPeerManager::WifiPeerManager()
+{
+	m_assocId = 0;
+	m_numberOfActivePeers = 0;
+	// firs peerLinkId is 1, because 0 means "unknown"
+	m_localLinkId = 1;
+	m_cleanupEvent = Simulator::Schedule (m_peerLinkCleanupPeriod, &WifiPeerManager::PeerCleanup, this);
+}
+WifiPeerManager::~WifiPeerManager()
+{
+	m_cleanupEvent.Cancel();
+	//TODO: delete a list of descriptors
+	for(
+			PeerDescriptorsMap::iterator j = m_peerDescriptors.begin();
+			j!= m_peerDescriptors.end();
+			j++)
+	{
+		int to_delete = 0;
+		for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = j->second.begin(); i!= j->second.end(); i++)
+		{
+			to_delete ++;
+			(*i)->ClearTimingElement();
+			(*i) = 0;
+		}
+		for(int i = 0; i < to_delete; i ++)
+			j->second.pop_back();
+		j->second.clear();
+	}
+	m_peerDescriptors.clear();
+
+}
+void
+WifiPeerManager::SetSentBeaconTimers(
+		Mac48Address portAddress, 
+		Time ReferenceTbtt,
+		Time BeaconInterval
+		)
+{
+	BeaconInfoMap::iterator myBeacon = m_myBeaconInfo.find(portAddress);
+	NS_ASSERT(myBeacon != m_myBeaconInfo.end());
+	myBeacon->second.referenceTbtt = ReferenceTbtt;
+	myBeacon->second.beaconInterval = BeaconInterval;
+
+}
+
+void
+WifiPeerManager::SetReceivedBeaconTimers(
+		Mac48Address portAddress, 
+		Mac48Address peerAddress,
+		Time lastBeacon,
+		Time beaconInterval,
+		WifiBeaconTimingElement beaconTiming
+		)
+{
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!=m_peerDescriptors.end());
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+	{
+		if((*i)->GetPeerAddress() == peerAddress)
+		{
+			(*i)->SetBeaconTimingElement(beaconTiming);
+			(*i)->SetBeaconInformation(lastBeacon, beaconInterval);
+			return;
+		}
+	}
+	Ptr<WifiPeerLinkDescriptor> new_descriptor =
+		AddDescriptor(portAddress, peerAddress, Simulator::Now(), beaconInterval);
+	new_descriptor->SetBeaconTimingElement(beaconTiming);
+}
+
+	bool
+WifiPeerManager::AttachPorts(std::vector<Ptr<WifiNetDevice> > ports)
+{
+	NS_ASSERT(ports.size()!=0);
+	for(std::vector<Ptr<WifiNetDevice> >::iterator i = ports.begin(); i != ports.end(); i++)
+	{
+		MeshWifiMac * meshWifiMac = dynamic_cast<MeshWifiMac *> (PeekPointer ((*i)->GetMac()));
+		if(meshWifiMac == NULL)
+			return false;
+		meshWifiMac->SetPeerLinkManager(this);
+		//Add a mac pointer:
+		m_macPointers[meshWifiMac->GetAddress()] = meshWifiMac;
+		//Add descriptor array:
+		std::vector<Ptr<WifiPeerLinkDescriptor> > descriptors;
+		m_peerDescriptors[meshWifiMac->GetAddress()] = descriptors;
+		//Add beacon timers:
+		struct BeaconInfo myBeacon;
+		m_myBeaconInfo[meshWifiMac->GetAddress()] = myBeacon;
+	}
+	return true;
+}
+	void
+WifiPeerManager::AskIfOpenNeeded(Mac48Address portAddress, Mac48Address peerAddress)
+{
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!=m_peerDescriptors.end());
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+		if((*i)->GetPeerAddress() == peerAddress)
+		{
+			if(ShouldSendOpen(portAddress, peerAddress))
+				(*i)->MLMEActivePeerLinkOpen();
+			break;
+		}
+}
+
+void
+WifiPeerManager::SetOpenReceived(
+		Mac48Address portAddress,
+		Mac48Address peerAddress,
+		PeerLinkManagementElement peerMan,
+		MeshConfigurationElement conf
+		)
+{
+	dot11sReasonCode reasonCode;
+	if(!ShouldAcceptOpen(portAddress, peerAddress,reasonCode))
+		return;
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!=m_peerDescriptors.end());
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+		if((*i)->GetPeerAddress() == peerAddress)
+		{
+			(*i)->PeerLinkOpenAccept(peerMan.GetLocalLinkId(), conf);
+			return;
+		}
+	 BeaconInfoMap::iterator myBeacon =  m_myBeaconInfo.find(portAddress);
+	 NS_ASSERT(myBeacon!=m_myBeaconInfo.end());
+	Ptr<WifiPeerLinkDescriptor>new_descriptor = AddDescriptor(
+			portAddress,
+			peerAddress,
+			Simulator::Now(),
+			myBeacon->second.beaconInterval
+			);
+	new_descriptor->PeerLinkOpenAccept(peerMan.GetLocalLinkId(), conf);
+}
+void
+WifiPeerManager::SetConfirmReceived(
+		Mac48Address portAddress,
+		Mac48Address peerAddress,
+		uint16_t peerAid,
+		PeerLinkManagementElement peerMan,
+		MeshConfigurationElement meshConfig
+		)
+{
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!= m_peerDescriptors.end());
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+		if((*i)->GetPeerAddress() == peerAddress)
+			(*i)->PeerLinkConfirmAccept(peerMan.GetLocalLinkId(), peerMan.GetPeerLinkId(), peerAid, meshConfig);
+}
+
+void
+WifiPeerManager::SetCloseReceived(
+		Mac48Address portAddress,
+		Mac48Address peerAddress,
+		PeerLinkManagementElement peerMan
+		)
+{
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!= m_peerDescriptors.end());
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+		if((*i)->GetPeerAddress() == peerAddress)
+		{
+			(*i)->PeerLinkClose(peerMan.GetLocalLinkId(), peerMan.GetPeerLinkId(), peerMan.GetReasonCode());
+			return;
+		}
+}
+
+void
+WifiPeerManager::ConfigurationMismatch(
+		Mac48Address portAddress,
+		Mac48Address peerAddress
+		)
+{
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!= m_peerDescriptors.end());
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+		if((*i)->GetPeerAddress() == peerAddress)
+		{
+			(*i)->MLMECancelPeerLink(MESH_CONFIGURATION_POLICY_VIOLATION);
+			return;
+		}
+
+}
+
+	WifiBeaconTimingElement
+WifiPeerManager::GetWifiBeaconTimingElementForMyBeacon(Mac48Address portAddress)
+{
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!= m_peerDescriptors.end());
+	WifiBeaconTimingElement return_val;
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+	{
+		//Just go through all neighbor entries and add it to timing element:
+		return_val.AddNeighboursTimingElementUnit(
+				(*i)->GetLocalAid(),
+				(*i)->GetLastBeacon(),
+				(*i)->GetBeaconInterval()
+				);
+	}
+	return return_val;
+
+}
+	WifiBeaconTimingElement
+WifiPeerManager::GetWifiBeaconTimingElementForAddress(
+		Mac48Address portAddress,
+		Mac48Address addr)
+{
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!= m_peerDescriptors.end());
+	WifiBeaconTimingElement return_val;
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+		if((*i)->GetPeerAddress() == addr)
+			return_val =  (*i)->GetBeaconTimingElement();
+	return return_val;
+
+
+}
+Ptr<WifiPeerLinkDescriptor>
+WifiPeerManager::AddDescriptor(
+		Mac48Address portAddress,
+		Mac48Address peerAddress,
+		Time lastBeacon,
+		Time beaconInterval)
+{
+	Ptr<WifiPeerLinkDescriptor> new_descriptor = Create<WifiPeerLinkDescriptor>();
+	if(m_assocId ==0xff)
+		m_assocId = 0;
+	if(m_localLinkId == 0xff)
+		m_localLinkId = 0;
+	new_descriptor->SetLocalAid(m_assocId++);
+	new_descriptor->SetLocalLinkId(m_localLinkId++);
+	new_descriptor->SetPeerAddress(peerAddress);
+	new_descriptor->SetBeaconInformation(lastBeacon, beaconInterval);
+	//DEBUG ONLY:
+	new_descriptor->SetLocalAddress(portAddress);
+	//check if port address is wrong
+	MeshMacMap::iterator pos = m_macPointers.find(portAddress);
+	NS_ASSERT(pos!= m_macPointers.end());
+	//check if descriptors array exist
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port !=m_peerDescriptors.end());
+	new_descriptor->SetMac(pos->second);
+	new_descriptor->SetMaxBeaconLoss(m_maxBeaconLoss);
+	new_descriptor->SetLinkStatusCallback(MakeCallback(&WifiPeerManager::PeerLinkStatus, this));
+	NS_ASSERT(port != m_peerDescriptors.end());
+	m_peerDescriptors[portAddress].push_back(new_descriptor);
+	return new_descriptor;
+}
+
+	void
+WifiPeerManager::PeerCleanup()
+{
+	for(
+		PeerDescriptorsMap::iterator j = m_peerDescriptors.begin();
+		j!= m_peerDescriptors.end();
+		j++)
+	{
+		std::vector<unsigned int> to_erase;
+		for(unsigned int i = 0; i< j->second.size(); i++)
+			if(j->second[i]->LinkIsIdle())
+			{
+				j->second[i]->ClearTimingElement();
+				j->second[i] = 0;
+				to_erase.push_back(i);
+			}
+		if(to_erase.size() == 0)
+			return;
+		for(unsigned int i = to_erase.size()-1 ; i >= 0; i--)
+			j->second.erase(j->second.begin() + to_erase[i]);
+		to_erase.clear();
+	}
+	m_cleanupEvent = Simulator::Schedule (m_peerLinkCleanupPeriod, &WifiPeerManager::PeerCleanup, this);
+}
+
+	std::vector<Mac48Address>
+WifiPeerManager::GetNeighbourAddressList(Mac48Address portAddress, Mac48Address peerAddress)
+{
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!= m_peerDescriptors.end());
+	std::vector<Mac48Address> return_value;
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+		return_value.push_back((*i)->GetPeerAddress());
+	return return_value;
+}
+
+	bool
+WifiPeerManager::IsActiveLink(Mac48Address portAddress, Mac48Address peerAddress)
+{
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!= m_peerDescriptors.end());
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+		if((*i)->GetPeerAddress() == peerAddress)
+			return ((*i)->LinkIsEstab());
+	return false;
+}
+
+	bool
+WifiPeerManager::ShouldSendOpen(Mac48Address portAddress, Mac48Address peerAddress)
+{
+	if(m_numberOfActivePeers > m_maxNumberOfPeerLinks)
+		return false;
+	return true;
+}
+
+	bool
+WifiPeerManager::ShouldAcceptOpen(Mac48Address portAddress, Mac48Address peerAddress,dot11sReasonCode & reasonCode)
+{
+	if(m_numberOfActivePeers > m_maxNumberOfPeerLinks)
+	{
+		reasonCode = MESH_MAX_PEERS;
+		return false;
+	}
+	return true;
+}
+
+	Time
+WifiPeerManager::GetNextBeaconShift(
+		Mac48Address portAddress,
+		Time myNextTBTT
+		)
+{
+	//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
+	//Im my MAC everything is stored in MicroSeconds
+
+	uint32_t myNextTBTTInTimeUnits = 0;
+	uint32_t futureBeaconInTimeUnits = 0;
+	//Going through all my timing elements and detecting future beacon collisions
+	PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress);
+	NS_ASSERT(port!= m_peerDescriptors.end());
+	BeaconInfoMap::iterator myBeacon = m_myBeaconInfo.find(portAddress);
+	NS_ASSERT(myBeacon!=m_myBeaconInfo.end());
+	for(std::vector<Ptr<WifiPeerLinkDescriptor> >::iterator i = port->second.begin(); i!= port->second.end(); i++)
+	{
+		NeighboursTimingUnitsList neighbours;
+		neighbours = (*i)->GetBeaconTimingElement().GetNeighboursTimingElementsList();
+		//first let's form the list of all kown TBTTs
+		for(NeighboursTimingUnitsList::const_iterator j = neighbours.begin(); j!= neighbours.end(); j++)
+		{
+			uint16_t beaconIntervalTimeUnits;
+			beaconIntervalTimeUnits = (*j)->GetBeaconInterval();
+
+			//The last beacon time in timing elememt in Time Units
+			uint32_t lastBeaconInTimeUnits;
+			lastBeaconInTimeUnits = (*j)->GetLastBeacon()/4;
+
+			//The time of my next beacon sending in Time Units
+			myNextTBTTInTimeUnits = myNextTBTT.GetMicroSeconds()/1024;
+
+			//My beacon interval in Time Units
+			uint32_t myBeaconIntervalInTimeUnits;
+			myBeaconIntervalInTimeUnits = myBeacon->second.beaconInterval.GetMicroSeconds()/1024;
+
+			//The time the beacon of other station will be sent
+			//we need the time just after my next TBTT (or equal to my TBTT)
+			futureBeaconInTimeUnits = lastBeaconInTimeUnits + beaconIntervalTimeUnits;
+
+			//We apply MBAC only if beacon Intervals are equal
+			if (beaconIntervalTimeUnits == myBeaconIntervalInTimeUnits)
+			{
+				//We know when the neighbor STA transmitted it's beacon
+				//Now we need to know when it's going to send it's beacon in the future
+				//So let's use the valuse of it's beacon interval
+				while (myNextTBTTInTimeUnits >= futureBeaconInTimeUnits)
+					futureBeaconInTimeUnits = futureBeaconInTimeUnits + beaconIntervalTimeUnits;
+				//If we found that my TBTT coincide with another STA's TBTT
+				//break all cylce and return time shift for my next TBTT
+				if (myNextTBTTInTimeUnits == futureBeaconInTimeUnits)
+					break;
+			}
+
+		}
+		if (myNextTBTTInTimeUnits == futureBeaconInTimeUnits)
+			break;
+	}
+
+	//TBTTs coincide, so let's calculate the shift
+	if (myNextTBTTInTimeUnits == futureBeaconInTimeUnits) {
+		NS_LOG_DEBUG("MBCA: Future beacon collision is detected, applying avoidance mechanism");
+		UniformVariable randomSign(-1, 1);
+		int coefficientSign = -1;
+		if (randomSign.GetValue() >= 0)
+			coefficientSign = 1;
+		UniformVariable randomShift(1, 15);
+		//So, the shift is a random integer variable uniformly distributed in [-15;-1] U [1;15]
+		int beaconShift = randomShift.GetInteger() * coefficientSign;
+		NS_LOG_DEBUG("Shift value = " << beaconShift << " beacon TUs");
+		//We need the result not in Time Units, but in microseconds
+		return MicroSeconds(beaconShift * 1024);
+	}
+	//No collision detecterf, hence no shift is needed
+	else
+		return MicroSeconds(0);
+}
+
+void
+WifiPeerManager::PeerLinkStatus(Mac48Address portAddress, Mac48Address peerAddress, bool status)
+{
+	MeshMacMap::iterator pos = m_macPointers.find(portAddress);
+	NS_ASSERT(pos!= m_macPointers.end());
+	pos->second->PeerLinkStatus(peerAddress, status);
+}
+} //namespace NS3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-peer-manager.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,329 @@
+/* -*-  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>
+ *          Ivan Pustogarov <chinsa1@rambler.ru>
+ *          Evgeny Khorov <horov@frtk.ru>
+ */
+
+
+#ifndef WIFI_PEER_MAN_H
+#define WIFI_PEER_MAN_H
+
+#include "ns3/event-id.h"
+#include "ns3/ptr.h"
+#include "ns3/nstime.h"
+#include "ns3/mac48-address.h"
+#include "ns3/uinteger.h"
+#include "ns3/wifi-net-device.h"
+#include "dot11s-peer-management-element.h"
+#include "mesh-wifi-beacon-timing-element.h"
+#include "mesh-wifi-mac.h"
+#include <list>
+
+namespace ns3
+{
+	class MeshWifiMac;
+	class WifiPeerLinkDescriptor : public RefCountBase
+	{
+		public:
+			WifiPeerLinkDescriptor();
+			/**
+			 * Beacon loss processing:
+			 */
+			void		SetBeaconInformation(Time lastBeacon, Time BeaconInterval);
+			void		SetMaxBeaconLoss(uint8_t maxBeaconLoss);
+			/**
+			 * \brief Methods used to detecet peer link changes
+			 * \param bool if true - opened new link, if
+			 * false - link closed
+			 */
+			void		SetLinkStatusCallback(Callback<void, Mac48Address, Mac48Address, bool> cb);
+			/**
+			 * Peer link geeters/setters
+			 */
+			void		SetPeerAddress(Mac48Address macaddr);
+			/**
+			 * Debug purpose
+			 */
+			void		SetLocalAddress(Mac48Address macaddr);
+			void		SetLocalLinkId(uint16_t id);
+			void		SetPeerLinkId(uint16_t id);
+			void		SetLocalAid(uint16_t aid);
+			void		SetPeerAid(uint16_t aid);
+			void		SetBeaconTimingElement(WifiBeaconTimingElement beaconTiming);
+			void		SetPeerLinkDescriptorElement(
+					PeerLinkManagementElement peerLinkElement
+					);
+			Mac48Address	GetPeerAddress()const;
+			/**
+			 * Debug purpose
+			 */
+			Mac48Address	GetLocalAddress()const;
+			uint16_t	GetLocalAid()const;
+			Time		GetLastBeacon()const;
+			Time		GetBeaconInterval()const;
+			WifiBeaconTimingElement
+					GetBeaconTimingElement()const;
+			PeerLinkManagementElement
+					GetPeerLinkDescriptorElement()const;
+			void		ClearTimingElement();
+			/* MLME */
+			void		MLMECancelPeerLink(dot11sReasonCode reason);
+			void		MLMEPassivePeerLinkOpen();
+			void		MLMEActivePeerLinkOpen();
+			void		MLMEPeeringRequestReject();
+#if 0
+			void		MLMEBindSecurityAssociation();
+#endif
+			void		SetMac(Ptr<MeshWifiMac> mac);
+			void		PeerLinkClose(uint16_t localLinkID,uint16_t peerLinkID, dot11sReasonCode reason);
+			void		PeerLinkOpenAccept(uint16_t localLinkId, MeshConfigurationElement  conf);
+			void		PeerLinkOpenReject(uint16_t localLinkId, MeshConfigurationElement  conf,dot11sReasonCode reason);
+			void		PeerLinkConfirmAccept(
+						uint16_t localLinkId,
+						uint16_t peerLinkId,
+						uint16_t peerAid,
+						MeshConfigurationElement  conf
+						);
+			void		PeerLinkConfirmReject(
+						uint16_t localLinkId,
+						uint16_t peerLinkId,
+						MeshConfigurationElement  conf,
+						dot11sReasonCode reason
+						);
+			bool		LinkIsEstab() const;
+			bool		LinkIsIdle() const;
+		private:
+			enum		PeerState {
+				IDLE,
+				LISTEN,
+				OPN_SNT,
+				CNF_RCVD,
+				OPN_RCVD,
+				ESTAB,
+				HOLDING,
+			};
+			enum		PeerEvent
+			{     
+				CNCL,		/** MLME-CancelPeerLink */
+				PASOPN,		/** MLME-PassivePeerLinkOpen */
+				ACTOPN,		/** MLME-ActivePeerLinkOpen */
+				//BNDSA,    	/** MLME-BindSecurityAssociation */
+				CLS_ACPT,	/** PeerLinkClose_Accept */
+				//CLS_IGNR,	/** PeerLinkClose_Ignore */
+				OPN_ACPT,	/** PeerLinkOpen_Accept */
+				//OPN_IGNR,	/** PeerLinkOpen_Ignore */
+				OPN_RJCT,	/** PeerLinkOpen_Reject */
+				REQ_RJCT,	/** PeerLinkOpenReject by internal reason */
+				CNF_ACPT,	/** PeerLinkConfirm_Accept */
+				//CNF_IGNR,	/** PeerLinkConfirm_Ignore */
+				CNF_RJCT,	/** PeerLinkConfirm_Reject */
+				TOR1,
+				TOR2,
+				TOC,
+				TOH,
+			};
+		private:
+			void	StateMachine(PeerEvent event,dot11sReasonCode = DOT11S_REASON_RESERVED);
+			/** Events handlers */
+			void	ClearRetryTimer();
+			void	ClearConfirmTimer();
+			void	ClearHoldingTimer();
+			void	SetHoldingTimer();
+			void	SetRetryTimer();
+			void	SetConfirmTimer();
+
+			void	SendPeerLinkClose(dot11sReasonCode reasoncode );
+			void	SendPeerLinkOpen();
+			void	SendPeerLinkConfirm();
+			/** Private Event */
+			void HoldingTimeout();
+			void RetryTimeout();
+			void ConfirmTimeout();
+		private:
+			Mac48Address	m_peerAddress;
+			Mac48Address	m_localAddress;
+			uint16_t	m_localLinkId;
+			uint16_t	m_peerLinkId;
+			// Used for beacon timing:
+			// All values are stored in microseconds!
+			Time		m_lastBeacon;
+			Time		m_beaconInterval;
+			uint16_t	m_assocId; //Assigned Assoc ID
+			uint16_t	m_peerAssocId; //Assoc Id assigned to me by peer
+			//State of our peer Link:
+			PeerState	m_state;
+
+			MeshConfigurationElement
+					m_configuration;
+			// State is a bitfield as defined as follows:
+			// This are states for a given 	
+			WifiBeaconTimingElement
+					m_beaconTiming;
+
+			EventId		m_retryTimer;
+			EventId		m_holdingTimer;
+			EventId		m_confirmTimer;
+			uint16_t	m_retryCounter;
+			/**
+			 * Beacon loss timers:
+			 */
+			EventId		m_beaconLossTimer;
+			uint8_t		m_maxBeaconLoss;
+			void		BeaconLoss();
+			Ptr<MeshWifiMac> m_mac;
+			Callback<void, Mac48Address, Mac48Address, bool>
+					m_linkStatusCallback;
+	};
+
+	class WifiPeerManager : public Object
+	{
+		public:
+			WifiPeerManager();
+			WifiPeerManager(Ptr<MeshWifiMac> mac_pointer);
+			~WifiPeerManager();
+			static	TypeId GetTypeId (void);
+			//Returns a beacon timing element stored for remote station:
+			WifiBeaconTimingElement
+				GetWifiBeaconTimingElementForAddress(Mac48Address portAddress, Mac48Address addr);
+			//Returns a list of all addresses, which beacons can be decoded:
+			std::vector<Mac48Address>
+				GetNeighbourAddressList(Mac48Address portAddress, Mac48Address peerAddress);
+			bool	AttachPorts(std::vector<Ptr<WifiNetDevice> >);
+			//void	SetMac(Ptr<MeshWifiMac> mac);
+			Time	GetNextBeaconShift(Mac48Address portAddress, Time myNextTBTT);
+
+			void	SetSentBeaconTimers(
+					Mac48Address	portAddress,
+					Time		ReferenceTBTT,
+					Time		BeaconInterval
+					);
+			void	AskIfOpenNeeded(
+					Mac48Address	portAddress,
+					Mac48Address	peerAddress
+					);
+			void	SetReceivedBeaconTimers(
+					Mac48Address	portAddress,
+					Mac48Address	peerAddress,
+					Time		lastBeacon,
+					Time		beaconInterval,
+					WifiBeaconTimingElement
+					beaconTiming
+					);
+			void	SetOpenReceived(
+					Mac48Address	portAddress,
+					Mac48Address	peerAddress,
+					PeerLinkManagementElement
+					peerMan,
+					MeshConfigurationElement conf
+					);
+			void	SetConfirmReceived(
+					Mac48Address	portAddress,
+					Mac48Address	peerAddress,
+					uint16_t	peerAid,
+					PeerLinkManagementElement
+					peerMan,
+					MeshConfigurationElement meshConfig
+					);
+			void	SetCloseReceived(
+					Mac48Address	portAddress,
+					Mac48Address	peerAddress,
+					PeerLinkManagementElement peerMan
+					);
+			//Using this function MAC
+			void	ConfigurationMismatch(
+					Mac48Address	portAddress,
+					Mac48Address	peerAddress
+					);
+			//Returns a beacon timing element to added into my beacon:
+			WifiBeaconTimingElement
+				GetWifiBeaconTimingElementForMyBeacon(
+					Mac48Address	portAddress
+					);
+			bool	IsActiveLink(
+					Mac48Address	portAddress,
+					Mac48Address	peerAddress
+					);
+		private:
+			struct BeaconInfo
+			{
+				Time	referenceTbtt;	//When one of my station's beacons was put into a beacon queue;
+				Time	beaconInterval;	//Beacon interval of my station;
+			};
+      typedef std::map<Mac48Address, std::vector<Ptr<WifiPeerLinkDescriptor> >, std::less<Mac48Address> >
+        PeerDescriptorsMap;
+    	typedef std::map<Mac48Address, Ptr<MeshWifiMac>,std::less<Mac48Address> > MeshMacMap;
+			typedef std::map<Mac48Address, struct BeaconInfo, std::less<Mac48Address> > BeaconInfoMap;
+
+			//Ptr<MeshWifiMac> m_mac;
+			//Maximum peers that may be opened:
+			uint8_t		m_maxNumberOfPeerLinks;
+			/**
+			 * Peer manager identify interface by address
+			 * of MAC. So, for every interface we store
+			 * list of peer descriptors.
+			 */
+			PeerDescriptorsMap m_peerDescriptors;
+			/**
+			 * List of MAC pointers - to iteract with each
+			 * mac
+			 */
+			MeshMacMap m_macPointers;
+			uint8_t		m_numberOfActivePeers;	//number of established peer links
+			uint16_t	m_assocId;		//last stored assoc ID
+			uint16_t	m_localLinkId;		//last stored local link ID
+			//This Variables used in beacon miss auto-cleanup:
+			//How many beacons may we lose before the link is
+			//considered to be broken:
+			uint8_t		m_maxBeaconLoss;
+			//Periodically we scan the peer manager list of peers
+			//and check if the too many  beacons were lost:
+			Time		m_peerLinkCleanupPeriod;
+			EventId		m_cleanupEvent;
+			Ptr<WifiPeerLinkDescriptor>
+				AddDescriptor(
+						Mac48Address portAddress,
+						Mac48Address peerAddress,
+						Time lastBeacon,
+						Time beaconInterval
+					     );
+			void		PeerCleanup();
+			//Mechanism of choosing PEERs:
+			bool		ShouldSendOpen(Mac48Address portAddress, Mac48Address peerAddress);
+			bool		ShouldAcceptOpen(
+						Mac48Address portAddress,
+						Mac48Address peerAddress,
+						dot11sReasonCode & reasonCode
+						);
+			//Needed for Beacon Collision Avoidance module:
+			BeaconInfoMap m_myBeaconInfo;
+			/**
+			 * Peer link Open/Close callbacks: We need to
+			 * inform MAC about this events.
+			 * \brief Interaction with peer link
+			 * descriptor - notify that peer link was
+			 * opened or closed
+			 * \param status true - peer link opened, peer
+			 * link closed otherwise
+			 */
+			void	PeerLinkStatus(Mac48Address portAddress, Mac48Address peerAddress, bool status);
+	};
+
+} //namespace ns3
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-perr-information-element.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,141 @@
+/* -*-  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: Yana Podkosova <yanapdk@rambler.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "mesh-wifi-perr-information-element.h"
+#include "ns3/address-utils.h"
+#define ELEMENT_ID (21)
+
+namespace ns3 {
+WifiPerrInformationElement::~WifiPerrInformationElement()
+{
+}
+
+TypeId
+WifiPerrInformationElement::GetTypeId()
+{
+	static TypeId tid = TypeId ("ns3::WifiPerrInformationElement")
+		.SetParent<Object> ();
+	return tid;
+}
+void
+WifiPerrInformationElement::Print(std::ostream &os) const
+{
+	// FILL
+}
+TypeId
+WifiPerrInformationElement::GetInstanceTypeId(void) const
+{
+	return GetTypeId();
+}
+WifiPerrInformationElement::WifiPerrInformationElement()
+{
+	m_numOfDest = 0;
+}
+uint8_t
+WifiPerrInformationElement::GetNumOfDest()
+{
+	return m_numOfDest;
+}
+void
+WifiPerrInformationElement::Serialize(Buffer::Iterator i)const
+{
+	i.WriteU8 (ELEMENT_ID);
+	i.WriteU8 (2+10*m_numOfDest);
+	i.WriteU8(0);
+	i.WriteU8 (m_numOfDest);
+	NS_ASSERT(m_numOfDest == m_addressUnits.size());
+	for(unsigned int j = 0; j < m_numOfDest; j++)
+	{
+		WriteTo(i,m_addressUnits[j].destination);
+		i.WriteHtonU32(m_addressUnits[j].seqnum);
+	}
+}
+uint32_t
+WifiPerrInformationElement::Deserialize(Buffer::Iterator start)
+{
+	Buffer::Iterator i = start;
+	uint8_t ElementId;
+	ElementId = i.ReadU8();
+	NS_ASSERT (ElementId = ELEMENT_ID);
+	int length = i.ReadU8();
+	i.Next(1); //Mode flags is not used now
+	m_numOfDest = i.ReadU8();
+	NS_ASSERT((2+10*m_numOfDest) == length);
+	length = 0; //to avoid compiler warning in optimized builds
+	for(unsigned int j = 0; j < m_numOfDest; j++)
+	{
+		struct HwmpRtable::FailedDestination unit;
+		ReadFrom(i,unit.destination);
+		unit.seqnum = i.ReadNtohU32();
+		m_addressUnits.push_back(unit);
+	}
+	return i.GetDistanceFrom(start);
+}
+
+uint32_t
+WifiPerrInformationElement::GetSerializedSize() const
+{
+	uint32_t retval = 
+		 1	//Element Id
+		 +1	//Length
+		 +1	//ModeFlags
+		 +1	//NumOfDests
+		 +6*m_numOfDest
+		 +4*m_numOfDest;
+	return retval;
+}
+
+void
+WifiPerrInformationElement::AddAddressUnit(struct HwmpRtable::FailedDestination unit)
+{
+	for(unsigned int i = 0; i < m_addressUnits.size(); i ++)
+		if(m_addressUnits[i].destination == unit.destination)
+			return;
+	m_addressUnits.push_back(unit);
+	m_numOfDest++;
+}
+
+std::vector<struct HwmpRtable::FailedDestination>
+WifiPerrInformationElement::GetAddressUnitVector()
+{
+	return m_addressUnits;
+}
+void
+WifiPerrInformationElement::DeleteAddressUnit(Mac48Address address)
+{
+	for(std::vector<struct HwmpRtable::FailedDestination>::iterator i = m_addressUnits.begin(); i != m_addressUnits.end(); i ++)
+		if((*i).destination == address)
+		{
+			m_numOfDest --;
+			m_addressUnits.erase(i);
+			break;
+		}
+}
+
+void
+WifiPerrInformationElement::ResetPerr()
+{
+	m_numOfDest = 0;
+	m_addressUnits.clear();
+}
+}//namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-perr-information-element.h	Sat Feb 28 14:21:05 2009 +0300
@@ -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: Yana Podkosova <yanapdk@rambler.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef PERR_INFORMATION_ELEMENT_H
+#define PERR_INFORMATION_ELEMENT_H 
+
+#include	<stdint.h>
+#include	"ns3/node.h"
+#include	"ns3/buffer.h"
+#include	"ns3/mac48-address.h"
+#include	"ns3/hwmp-rtable.h"
+#include	"ns3/header.h"
+
+namespace ns3
+{
+class WifiPerrInformationElement : public Header
+{
+	public:
+		WifiPerrInformationElement();
+		~WifiPerrInformationElement();
+		static TypeId		GetTypeId(void);
+		virtual TypeId		GetInstanceTypeId(void) const;
+		virtual void		Print(std::ostream &os) const;
+		virtual void		Serialize(Buffer::Iterator i) const;
+		virtual uint32_t	Deserialize(Buffer::Iterator start);
+		virtual uint32_t	GetSerializedSize() const;
+#if 0
+		//RESERVED in D2.07
+		uint8_t			GetModeFlags();
+		void			SetModeFlags(uint8_t flags);
+#endif
+		uint8_t			GetNumOfDest();
+
+		void			AddAddressUnit(struct HwmpRtable::FailedDestination unit);
+		std::vector<struct HwmpRtable::FailedDestination>
+					GetAddressUnitVector();
+		void			DeleteAddressUnit(Mac48Address address);
+		void			ResetPerr();
+	private:
+		uint8_t			m_numOfDest;
+		std::vector<struct HwmpRtable::FailedDestination>
+					m_addressUnits;
+};
+
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-prep-information-element.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,219 @@
+/* -*-  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: Yana Podkosova <yanapdk@rambler.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "mesh-wifi-prep-information-element.h"
+#include "ns3/address-utils.h"
+#include "ns3/assert.h"
+#define ELEMENT_ID (30)
+namespace ns3{ 
+/********************************
+ * WifiPrepInformationElement
+ *******************************/
+WifiPrepInformationElement::~WifiPrepInformationElement()
+{
+}
+
+TypeId
+WifiPrepInformationElement::GetTypeId()
+{
+	static TypeId tid = TypeId ("ns3::WifiPrepInformationElement")
+		.SetParent<Object> ();
+	return tid;
+}
+void
+WifiPrepInformationElement::Print(std::ostream &os) const
+{
+	//TODO:fill this method
+}
+TypeId
+WifiPrepInformationElement::GetInstanceTypeId(void) const
+{
+	return GetTypeId();
+}
+WifiPrepInformationElement::WifiPrepInformationElement()
+{
+	m_flags = 0;
+        m_hopcount = 0;
+	m_ttl = 0;
+	m_destSeqNumber = 0;
+	m_lifetime = 0;
+	m_destinationAddress = Mac48Address::GetBroadcast();
+	m_metric = 0;
+	m_originatorSeqNumber = 0;
+}
+void
+WifiPrepInformationElement::SetFlags(uint8_t flags)
+{
+	m_flags = flags;
+}
+void
+WifiPrepInformationElement::SetHopcount(uint8_t hopcount)
+{
+	m_hopcount = hopcount;
+}
+void
+WifiPrepInformationElement::SetTTL(uint8_t ttl)
+{
+	m_ttl = ttl;
+}
+void
+WifiPrepInformationElement::SetDestinationSeqNumber(uint32_t dest_seq_number)
+{
+	m_destSeqNumber = dest_seq_number;
+}
+void
+WifiPrepInformationElement::SetDestinationAddress(Mac48Address dest_address)
+{
+	m_destinationAddress = dest_address;
+}
+void
+WifiPrepInformationElement::SetMetric(uint32_t metric)
+{
+	m_metric = metric;
+}
+void 
+WifiPrepInformationElement::SetOriginatorAddress(Mac48Address originator_address)
+{
+	m_originatorAddress = originator_address;
+}
+void
+WifiPrepInformationElement::SetOriginatorSeqNumber(uint32_t originator_seq_number)
+{
+	m_originatorSeqNumber = originator_seq_number;
+}
+void 
+WifiPrepInformationElement::SetLifetime(uint32_t lifetime)
+{
+	m_lifetime = lifetime;
+}
+uint8_t
+WifiPrepInformationElement::GetFlags() const
+{
+	return m_flags;
+}
+uint8_t
+WifiPrepInformationElement::GetHopcount() const 
+{
+	return m_hopcount;
+}
+uint32_t
+WifiPrepInformationElement::GetTTL() const
+{
+	return m_ttl;
+}
+uint32_t
+WifiPrepInformationElement::GetDestinationSeqNumber() const
+{
+	return m_destSeqNumber;
+}
+Mac48Address
+WifiPrepInformationElement::GetDestinationAddress() const
+{
+	return m_destinationAddress;
+}
+uint32_t 
+WifiPrepInformationElement::GetMetric() const
+{
+	return m_metric;
+}
+Mac48Address
+WifiPrepInformationElement::GetOriginatorAddress() const
+{
+	return m_originatorAddress;
+}
+uint32_t
+WifiPrepInformationElement::GetOriginatorSeqNumber() const
+{
+	return m_originatorSeqNumber;
+}
+uint32_t 
+WifiPrepInformationElement::GetLifetime() const
+{
+	return m_lifetime;
+}
+void
+WifiPrepInformationElement::DecrementTtl()
+{
+	m_ttl --;
+}
+
+void
+WifiPrepInformationElement::IncrementMetric(uint32_t metric)
+{
+	m_metric +=metric;
+}
+
+
+void
+WifiPrepInformationElement::Serialize(Buffer::Iterator i) const
+{
+	i.WriteU8 (ELEMENT_ID);
+	i.WriteU8 (32);//length = 32
+	i.WriteU8 (m_flags);
+	i.WriteU8 (m_hopcount);
+	i.WriteU8 (m_ttl);
+	WriteTo(i, m_destinationAddress);
+	i.WriteHtonU32 (m_destSeqNumber);
+	i.WriteHtonU32 (m_lifetime);
+	i.WriteHtonU32 (m_metric);
+	WriteTo(i, m_originatorAddress);
+	i.WriteHtonU32 (m_originatorSeqNumber);
+}
+uint32_t
+WifiPrepInformationElement::Deserialize(Buffer::Iterator start)
+{
+	Buffer::Iterator i = start;
+	uint8_t ElementId;
+	ElementId = i.ReadU8();
+	NS_ASSERT (ElementId == ELEMENT_ID);
+	i.Next(1); // length is constatnt
+	m_flags = i.ReadU8();
+	m_hopcount = i.ReadU8();
+	m_ttl = i.ReadU8();
+	ReadFrom(i,m_destinationAddress);
+	m_destSeqNumber = i.ReadNtohU32();
+	m_lifetime = i.ReadNtohU32();
+	m_metric = i.ReadNtohU32();
+	ReadFrom(i,m_originatorAddress);
+	m_originatorSeqNumber = i.ReadNtohU32();
+	return i.GetDistanceFrom(start);
+}
+uint32_t
+WifiPrepInformationElement::GetSerializedSize() const
+{
+	uint32_t retval = 
+		 1	//Element ID
+		+1	//Length
+		+1	//Flags
+		+1	//Hopcount
+		+1	//TTL
+		+6	//Dest address 
+		+4	//Dest seqno
+		+4	//Lifetime
+		+4	//metric
+		+6	//Originator address
+		+4	//Originator seqno
+		+1;	//destination count
+		return retval;
+
+};
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-prep-information-element.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,81 @@
+/* -*-  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: Yana Podkosova <yanapdk@rambler.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef WIFI_PREP_INFORMATION_ELEMENT_H
+#define WIFI_PREP_INFORMATION_ELEMENT_H
+
+
+#include	<stdint.h>
+#include	"ns3/node.h"
+#include	"ns3/buffer.h"
+#include	"ns3/mac48-address.h"
+#include	"ns3/header.h"
+namespace ns3
+{
+class WifiPrepInformationElement : public Header
+{
+	public:
+		WifiPrepInformationElement();
+		~WifiPrepInformationElement();
+		static TypeId GetTypeId(void);
+		virtual TypeId GetInstanceTypeId(void) const;
+		virtual void Print(std::ostream &os) const;
+	        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_seg_number);
+		virtual void Serialize(Buffer::Iterator i) const;
+		virtual uint32_t Deserialize(Buffer::Iterator i);
+		virtual uint32_t GetSerializedSize() const; 
+
+		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);
+	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;		
+};
+}//namespace ns3
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-preq-information-element.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -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
+ *
+ * Authors: Yana Podkosova <yanapdk@rambler.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "mesh-wifi-preq-information-element.h"
+#include "ns3/address-utils.h"
+#include "ns3/assert.h"
+#define ELEMENT_ID (22)
+namespace ns3{
+/*************************
+ * DestinationAddressUnit
+ ************************/
+DestinationAddressUnit::DestinationAddressUnit()
+{
+        m_do = false;
+	m_rf = false;
+	m_destSeqNumber = 0;
+	uint8_t mac_buffer[6];
+	for (int j = 0; j < 6; j++)
+	{
+		mac_buffer[j] = 0;
+	}
+	m_destinationAddress.CopyFrom(mac_buffer);
+}
+void
+DestinationAddressUnit::SetFlags(bool doFlag, bool rfFlag)
+{
+	m_do = doFlag;
+	m_rf = rfFlag;
+}
+
+void
+DestinationAddressUnit::SetDestSeqNumber(uint32_t dest_seq_number)
+{
+	m_destSeqNumber = dest_seq_number;
+}
+void 
+DestinationAddressUnit::SetDestinationAddress(Mac48Address dest_address)
+{
+	m_destinationAddress = dest_address;
+}
+bool
+DestinationAddressUnit::IsDo()
+{
+	return m_do;
+}
+
+bool
+DestinationAddressUnit::IsRf()
+{
+	return m_rf;
+}
+
+uint32_t
+DestinationAddressUnit::GetDestSeqNumber() const
+{
+	return m_destSeqNumber;
+}
+Mac48Address 
+DestinationAddressUnit::GetDestinationAddress() const
+{
+	return m_destinationAddress;
+}
+/********************************
+ * WifiPreqInformationElement
+ *******************************/
+WifiPreqInformationElement::~WifiPreqInformationElement()
+{
+}
+
+TypeId
+WifiPreqInformationElement::GetTypeId()
+{
+	static TypeId tid = TypeId ("ns3::WifiPreqInformationElement")
+		.SetParent<Object> ();
+	return tid;
+}
+void
+WifiPreqInformationElement::Print(std::ostream &os) const
+{
+	//TODO:fill this method
+}
+
+TypeId
+WifiPreqInformationElement::GetInstanceTypeId(void) const
+{
+	return GetTypeId();
+}
+
+WifiPreqInformationElement::WifiPreqInformationElement()
+{
+	m_flags = 0;
+        m_hopCount = 0;
+	m_ttl = 0;
+	m_preqId = 0;
+	m_lifetime = 0;
+	m_originatorAddress = Mac48Address::GetBroadcast();
+	m_originatorSeqNumber = 0;
+	m_metric = 0;
+	m_destCount = 0;
+	m_maxSize = DEF_MAX_SIZE;
+}
+void
+WifiPreqInformationElement::SetUnicastPreq()
+{
+	m_flags |= 1<<1;
+}
+
+void
+WifiPreqInformationElement::SetNeedNotPrep()
+{
+	m_flags |= 1<<2;
+}
+//void
+//WifiPreqInformationElement::SetFlags(uint8_t flags)
+//{
+//	m_flags = flags;
+//}
+void
+WifiPreqInformationElement::SetHopcount(uint8_t hopcount)
+{
+	m_hopCount = hopcount;
+}
+void
+WifiPreqInformationElement::SetTTL(uint8_t ttl)
+{
+	m_ttl = ttl;
+}
+void
+WifiPreqInformationElement::SetPreqID(uint32_t preq_id)
+{
+	m_preqId = preq_id;
+}
+void
+WifiPreqInformationElement::SetMetric(uint32_t metric)
+{
+	m_metric = metric;
+}
+void 
+WifiPreqInformationElement::SetOriginatorAddress(Mac48Address originator_address)
+{
+	m_originatorAddress = originator_address;
+}
+void
+WifiPreqInformationElement::SetOriginatorSeqNumber(uint32_t originator_seq_number)
+{
+	m_originatorSeqNumber = originator_seq_number;
+}
+void 
+WifiPreqInformationElement::SetLifetime(uint32_t lifetime)
+{
+	m_lifetime = lifetime;
+}
+void
+WifiPreqInformationElement::SetDestCount(uint8_t dest_count)
+{
+	m_destCount = dest_count;
+}
+
+//uint8_t
+//WifiPreqInformationElement::GetFlags() const
+//{
+//	return m_flags;
+//}
+bool
+WifiPreqInformationElement::IsUnicastPreq() const
+{
+	return (m_flags & (1<<1));
+}
+
+bool
+WifiPreqInformationElement::IsNeedNotPrep() const
+{
+	return (m_flags & (1<<2));
+}
+
+uint8_t
+WifiPreqInformationElement::GetHopCount() const
+{
+	return m_hopCount;
+}
+uint8_t
+WifiPreqInformationElement::GetTtl() const
+{
+	return m_ttl;
+}
+uint32_t
+WifiPreqInformationElement::GetPreqID() const
+{
+	return m_preqId;
+}
+uint32_t 
+WifiPreqInformationElement::GetMetric() const
+{
+	return m_metric;
+}
+Mac48Address
+WifiPreqInformationElement::GetOriginatorAddress() const
+{
+	return m_originatorAddress;
+}
+uint32_t
+WifiPreqInformationElement::GetOriginatorSeqNumber() const
+{
+	return m_originatorSeqNumber;
+}
+uint32_t 
+WifiPreqInformationElement::GetLifetime() const
+{
+	return m_lifetime;
+}
+
+uint8_t
+WifiPreqInformationElement::GetDestCount() const
+{
+	return m_destCount;
+}
+
+void
+WifiPreqInformationElement::DecrementTtl()
+{
+	m_ttl --;
+	m_hopCount ++;
+}
+
+void
+WifiPreqInformationElement::IncrementMetric(uint32_t metric)
+{
+	m_metric +=metric;
+}
+
+void
+WifiPreqInformationElement::Serialize(Buffer::Iterator i) const
+{
+	i.WriteU8 (ELEMENT_ID);
+	//TODO:Check maxsize
+	uint8_t length = m_destCount*11+28;
+	if(m_destCount> m_maxSize)
+		length -=(m_destCount-m_maxSize)*11;
+	i.WriteU8(length);
+	i.WriteU8 (m_flags);
+	i.WriteU8 (m_hopCount);
+	i.WriteU8 (m_ttl);
+	i.WriteHtonU32 (m_preqId);
+	WriteTo(i, m_originatorAddress);
+	i.WriteHtonU32 (m_originatorSeqNumber);
+	i.WriteHtonU32 (m_lifetime);
+	i.WriteHtonU32 (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 +=128;
+		if((*j)->IsRf())
+			flags +=64;
+		i.WriteU8(flags);
+		WriteTo(i,(*j)->GetDestinationAddress());
+		i.WriteHtonU32 ((*j)->GetDestSeqNumber());
+		written++;
+		if (written > m_maxSize)
+			break;
+	}
+}
+
+uint32_t
+WifiPreqInformationElement::Deserialize(Buffer::Iterator start)
+{
+	Buffer::Iterator i = start;
+	uint8_t ElementId;
+	ElementId = i.ReadU8();
+	NS_ASSERT (ElementId == ELEMENT_ID);
+	uint8_t length;
+	length = i.ReadU8();
+	m_flags = i.ReadU8();
+	m_hopCount = i.ReadU8();
+	m_ttl = i.ReadU8();
+	m_preqId = i.ReadNtohU32();
+	ReadFrom(i,m_originatorAddress);
+	m_originatorSeqNumber = i.ReadNtohU32();
+        m_lifetime = i.ReadNtohU32();
+	m_metric = i.ReadNtohU32();
+	m_destCount = i.ReadU8();
+	for (int j = 0; j < m_destCount; j++ )
+	{
+		Ptr<DestinationAddressUnit> new_element = Create<DestinationAddressUnit>();
+		bool doFlag = false;
+		bool rfFlag = false;
+		uint8_t flags = i.ReadU8();
+		if(flags >= 128)
+		{
+			doFlag = true;
+			flags -=128;
+		}
+		if(flags >=64)
+			rfFlag = true;
+		new_element->SetFlags(doFlag, rfFlag);
+		Mac48Address addr;
+		ReadFrom(i,addr);
+		new_element->SetDestinationAddress(addr);
+		new_element->SetDestSeqNumber(i.ReadNtohU32());
+		m_destinations.push_back(new_element);
+		NS_ASSERT(28+j*11 < length);
+	}
+	return i.GetDistanceFrom(start);
+}
+uint32_t
+WifiPreqInformationElement::GetSerializedSize() const
+{
+	uint32_t retval = 
+		 1	//Element ID
+		+1	//Length
+		+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;
+}
+std::vector<Ptr<DestinationAddressUnit> >
+WifiPreqInformationElement::GetDestinationList()
+{
+	return m_destinations;
+}
+void
+WifiPreqInformationElement::AddDestinationAddressElement(
+		bool doFlag, bool rfFlag,
+		Mac48Address dest_address,
+                uint32_t dest_seq_number
+		)
+{
+	for(std::vector<Ptr<DestinationAddressUnit> >::iterator i = m_destinations.begin(); i!=m_destinations.end(); i++ )
+		if((*i)->GetDestinationAddress() == dest_address)
+			return;
+	Ptr<DestinationAddressUnit>new_element = Create<DestinationAddressUnit>();
+	new_element->SetFlags(doFlag, rfFlag);
+	new_element->SetDestinationAddress(dest_address);
+	new_element->SetDestSeqNumber(dest_seq_number);
+	m_destinations.push_back(new_element);
+	m_destCount++;
+}
+
+void
+WifiPreqInformationElement::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
+WifiPreqInformationElement::ClearDestinationAddressElement()
+{
+	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();
+};
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-preq-information-element.h	Sat Feb 28 14:21:05 2009 +0300
@@ -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: Yana Podkosova <yanapdk@rambler.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef WIFI_PREQ_INFORMATION_ELEMENT_H
+#define WIFI_PREQ_INFORMATION_ELEMENT_H
+
+#include	<stdint.h>
+#include	"ns3/node.h"
+#include	"ns3/buffer.h"
+#include	"ns3/mac48-address.h"
+#include	"ns3/header.h"
+#include	<vector>
+namespace ns3
+{
+class DestinationAddressUnit : public RefCountBase
+{
+	public:
+		DestinationAddressUnit();
+		void	SetFlags(bool doFlag, bool rfflag);
+		//void SetPerDestFlags(uint8_t per_dest_flags);
+		void SetDestinationAddress(Mac48Address dest_address);
+		void SetDestSeqNumber(uint32_t dest_seq_number);
+		bool IsDo();
+		bool IsRf();
+		Mac48Address GetDestinationAddress() const;
+		uint32_t GetDestSeqNumber() const;
+
+	private:
+		bool m_do;
+		bool m_rf;
+		Mac48Address m_destinationAddress;
+		uint32_t m_destSeqNumber;
+};	
+
+class WifiPreqInformationElement : public Header
+{
+	public:
+		WifiPreqInformationElement();
+		~WifiPreqInformationElement (void);
+		static TypeId GetTypeId (void);
+		virtual TypeId GetInstanceTypeId(void) const;
+		virtual void Print(std::ostream &os) const;
+		void AddDestinationAddressElement(
+			bool doFlag,
+			bool rfFlag,
+			Mac48Address dest_address,
+			uint32_t dest_seq_number
+		 	);
+                void DelDestinationAddressElement(Mac48Address dest_address);
+		void ClearDestinationAddressElement();
+                std::vector<Ptr<DestinationAddressUnit> > GetDestinationList ();
+		//void SetFlags(uint8_t flags);
+		void SetUnicastPreq();
+		/*
+		 * \brief In proactive case: need we send PREP
+		 */
+		void SetNeedNotPrep();
+		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);
+
+                virtual void Serialize(Buffer::Iterator i) const;
+		virtual uint32_t Deserialize(Buffer::Iterator i);
+		virtual uint32_t GetSerializedSize() const;
+
+		//uint8_t		GetFlags() const ;
+		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;
+		void		DecrementTtl();
+		void		IncrementMetric(uint32_t metric);
+
+	private:
+		std::vector<Ptr<DestinationAddressUnit> >
+				m_destinations;
+		//how many destinations we support
+		uint8_t	m_maxSize;
+		//Fields:
+		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;
+#define DEF_MAX_SIZE	32
+};
+
+} //namespace ns3
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-rann-information-element.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -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
+ *
+ * Authors: Yana Podkosova <yanapdk@rambler.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "mesh-wifi-rann-information-element.h"
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#define ELEMENT_ID (20)
+
+namespace ns3{
+
+WifiRannInformationElement::~WifiRannInformationElement()
+{
+}
+TypeId
+WifiRannInformationElement::GetTypeId()
+{
+	static TypeId tid = TypeId ("ns3::WifiRannInformationElement").SetParent<Object> ();
+	return tid;
+}
+TypeId
+WifiRannInformationElement::GetInstanceTypeId(void) const
+{
+	return GetTypeId();
+}
+void
+WifiRannInformationElement::Print(std::ostream &os)const
+{
+	// FILL
+}
+WifiRannInformationElement::WifiRannInformationElement()
+{	m_flags = 0;
+	m_hopcount = 0;
+	m_ttl = 0;
+	m_destSeqNumber = 0;
+	m_metric = 0;
+	m_originatorAddress = Mac48Address::GetBroadcast();
+	m_destSeqNumber = 0;
+	
+}
+void
+WifiRannInformationElement::SetFlags(uint8_t flags)
+{
+	m_flags = flags;
+}
+void
+WifiRannInformationElement::SetHopcount(uint8_t hopcount)
+{
+	m_hopcount = hopcount;
+}
+void
+WifiRannInformationElement::SetTTL(uint8_t ttl)
+{
+	m_ttl = ttl;
+}
+void
+WifiRannInformationElement::SetDestSeqNumber(uint32_t dest_seq_number)
+{
+	m_destSeqNumber = dest_seq_number;
+}
+void
+WifiRannInformationElement::SetMetric(uint32_t metric)
+{
+	m_metric = metric;
+}
+void 
+WifiRannInformationElement::SetOriginatorAddress(Mac48Address originator_address)
+{
+	m_originatorAddress = originator_address;
+}
+
+uint8_t
+WifiRannInformationElement::GetFlags()
+{
+	return m_flags;
+}
+uint8_t
+WifiRannInformationElement::GetHopcount()
+{
+	return m_hopcount;
+}
+uint8_t
+WifiRannInformationElement::GetTTL()
+{
+	return m_ttl;
+}
+uint32_t
+WifiRannInformationElement::GetDestSeqNumber()
+{
+	return m_destSeqNumber;
+}
+uint32_t 
+WifiRannInformationElement::GetMetric()
+{
+	return m_metric;
+}
+Mac48Address
+WifiRannInformationElement::GetOriginatorAddress()
+{
+	return m_originatorAddress;
+}
+void
+WifiRannInformationElement::Serialize(Buffer::Iterator i) const
+{
+	i.WriteU8 (ELEMENT_ID);
+	i.WriteU8 (21);//length = 21
+	i.WriteU8 (m_flags);
+	i.WriteU8 (m_hopcount);
+	i.WriteU8 (m_ttl);
+	WriteTo(i, m_originatorAddress);
+	i.WriteHtonU32 (m_destSeqNumber);
+	i.WriteHtonU32 (m_metric);
+}
+uint32_t
+WifiRannInformationElement::Deserialize(Buffer::Iterator start)
+{
+	Buffer::Iterator i = start;
+	uint8_t ElementId;
+        ElementId = i.ReadU8();
+	NS_ASSERT (ElementId == ELEMENT_ID);
+        i.Next(1);// length is constant
+	m_flags = i.ReadU8();
+	m_hopcount = i.ReadU8();
+	m_ttl = i.ReadU8();
+	ReadFrom(i, m_originatorAddress);
+	m_destSeqNumber = i.ReadNtohU32();
+	m_metric = i.ReadNtohU32();
+	return i.GetDistanceFrom(start);
+}
+uint32_t
+WifiRannInformationElement::GetSerializedSize() const
+{
+	uint32_t retval = 
+		 1//ElementId
+		+1//Length
+		+1//Flags
+		+1//Hopcount
+		+1//TTL
+		+6//OriginatorAddress
+		+4//DestSeqNumber
+		+4;//Metric
+	return retval;
+};
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/mesh-wifi-rann-information-element.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,72 @@
+/* -*-  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: Yana Podkosova <yanapdk@rambler.ru>
+ *          Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#ifndef RANN_INFORMATION_ELEMENT_H
+#define RANN_INFORMATION_ELEMENT_H
+
+
+#include	<stdint.h>
+#include	"ns3/buffer.h"
+#include	"ns3/mac48-address.h"
+#include	"ns3/node.h"
+#include	"ns3/header.h"
+
+namespace ns3
+{
+class WifiRannInformationElement
+{
+	public:
+		WifiRannInformationElement();
+		virtual ~WifiRannInformationElement();
+		static TypeId GetTypeId(void);
+		virtual TypeId GetInstanceTypeId(void) const;
+		virtual void Print(std::ostream &os) const;
+		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);
+		virtual void Serialize(Buffer::Iterator i) const;
+		virtual uint32_t Deserialize(Buffer::Iterator start);
+	        virtual uint32_t GetSerializedSize() const;
+		uint8_t GetFlags();
+		uint8_t GetHopcount();
+		uint8_t GetTTL();
+		Mac48Address GetOriginatorAddress();
+		uint32_t GetDestSeqNumber();
+		uint32_t GetMetric();
+
+		void DecrementTtl();
+		void IncrementMetric(uint32_t metric);
+
+	private:
+		uint8_t m_flags;
+		uint8_t m_hopcount;
+		uint8_t m_ttl;
+		Mac48Address m_originatorAddress;
+		uint32_t m_destSeqNumber;
+		uint32_t m_metric; 
+};
+
+}
+#endif
--- a/src/devices/wifi/mgt-headers.cc	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/devices/wifi/mgt-headers.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -20,6 +20,8 @@
 #include "mgt-headers.h"
 #include "ns3/simulator.h"
 #include "ns3/assert.h"
+#include "ns3/log.h"
+NS_LOG_COMPONENT_DEFINE("MgtHeaders");
 
 namespace ns3 {
 
@@ -109,6 +111,11 @@
 MgtProbeResponseHeader::~MgtProbeResponseHeader ()
 {}
 
+uint64_t
+MgtProbeResponseHeader::GetTimestamp()
+{
+	return m_timestamp;
+}
 Ssid 
 MgtProbeResponseHeader::GetSsid (void) const
 {
@@ -198,7 +205,7 @@
 MgtProbeResponseHeader::Deserialize (Buffer::Iterator start)
 {
   Buffer::Iterator i = start;
-  i.Next (8); // timestamp
+  m_timestamp = i.ReadNtohU64();
   m_beaconInterval = i.ReadNtohU16 ();
   m_beaconInterval *= 1024;
   i = m_capability.Deserialize (i);
@@ -207,6 +214,71 @@
   //i.Next (3); // ds parameter set
   return i.GetDistanceFrom (start);
 }
+/***********************************************************
+ *          Mesh Beacon
+ ***********************************************************/
+void
+MgtMeshBeaconHeader::SetMeshConfigurationElement(MeshConfigurationElement mesh_config)
+{
+	m_meshConfig = mesh_config;
+}
+
+void
+MgtMeshBeaconHeader::SetWifiBeaconTimingElement(WifiBeaconTimingElement wifi_timing)
+{
+	m_meshTiming = wifi_timing;
+}
+
+MeshConfigurationElement
+MgtMeshBeaconHeader::GetMeshConfigurationElement()
+{
+	return m_meshConfig;
+}
+
+WifiBeaconTimingElement
+MgtMeshBeaconHeader::GetWifiBeaconTimingElement()
+{
+	return m_meshTiming;
+}
+
+uint32_t
+MgtMeshBeaconHeader::GetSerializedSize (void) const
+{
+	uint32_t size = (
+			  MgtBeaconHeader::GetSerializedSize()
+			+ m_meshConfig.GetSerializedSize()
+			+ m_meshTiming.GetSerializedSize()
+			+ 9 //MSCIE
+			);
+        return size;
+}
+
+void
+MgtMeshBeaconHeader::Serialize (Buffer::Iterator start) const
+{
+	//First we pack Beacon:
+  NS_LOG_DEBUG("Serialization beacon");
+	Buffer::Iterator i = start;
+	MgtBeaconHeader::Serialize(i);
+	i.Next(MgtBeaconHeader::GetSerializedSize());
+	i = m_meshConfig.Serialize(i);
+	i = m_meshTiming.Serialize(i);
+	i.Next(9); //MSCIE
+}
+
+uint32_t
+MgtMeshBeaconHeader::Deserialize (Buffer::Iterator start)
+{
+        NS_LOG_DEBUG("Deserialization beacon");
+	Buffer::Iterator i = start;
+	MgtBeaconHeader::Deserialize(start);
+	i.Next(MgtBeaconHeader::GetSerializedSize());
+	i = m_meshConfig.Deserialize(i);
+	i = m_meshTiming.Deserialize(i);
+	i.Next(9); //MSCIE
+	return i.GetDistanceFrom (start);
+}
+
 
 /***********************************************************
  *          Assoc Request
--- a/src/devices/wifi/mgt-headers.h	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/devices/wifi/mgt-headers.h	Sat Feb 28 14:21:05 2009 +0300
@@ -21,11 +21,14 @@
 #define MGT_HEADERS_H
 
 #include <stdint.h>
+#include <vector>
 
 #include "ns3/header.h"
 #include "status-code.h"
 #include "capability-information.h"
 #include "supported-rates.h"
+#include "mesh-configuration-element.h"
+#include "mesh-wifi-beacon-timing-element.h"
 #include "ssid.h"
 
 namespace ns3 {
@@ -117,6 +120,8 @@
   void SetBeaconIntervalUs (uint64_t us);
   void SetSupportedRates (SupportedRates rates);
 
+  uint64_t GetTimestamp();
+
   static TypeId GetTypeId (void);
   virtual TypeId GetInstanceTypeId (void) const;
   virtual void Print (std::ostream &os) const;
@@ -125,6 +130,7 @@
   virtual uint32_t Deserialize (Buffer::Iterator start);
 
 private:
+  uint64_t m_timestamp;
   Ssid m_ssid;
   uint64_t m_beaconInterval;
   SupportedRates m_rates;
@@ -132,6 +138,22 @@
 };
 
 class MgtBeaconHeader : public MgtProbeResponseHeader {};
+class MgtMeshBeaconHeader : public MgtBeaconHeader
+{
+	public:
+		void				SetMeshConfigurationElement(MeshConfigurationElement mesh_config);
+		void				SetWifiBeaconTimingElement(WifiBeaconTimingElement wifi_timing);
+		MeshConfigurationElement	GetMeshConfigurationElement();
+		WifiBeaconTimingElement		GetWifiBeaconTimingElement();
+		virtual uint32_t		GetSerializedSize (void) const;
+		virtual void			Serialize (Buffer::Iterator start) const;
+		virtual uint32_t		Deserialize (Buffer::Iterator start);
+
+	private:
+		MeshConfigurationElement	m_meshConfig;
+		WifiBeaconTimingElement		m_meshTiming;
+
+};
 
 
 } // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/tx-statistics.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,186 @@
+/* -*-  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/tx-statistics.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("WifiTxStatistics");
+
+namespace ns3 {
+
+TypeId
+WifiTxStatistics::GetTypeId(void)
+{
+	static TypeId tid = TypeId("ns3::WifiTxStatistics")
+		.SetParent<Object> ()
+		.AddConstructor<WifiTxStatistics> ();
+	return tid;
+}
+WifiTxStatistics::WifiTxStatistics():
+	m_numOfGroups(10),
+	m_maxLength(2500)
+{
+}
+WifiTxStatistics::~WifiTxStatistics()
+{
+}
+void
+WifiTxStatistics::SetLengthDivisionParams(uint16_t maxLength, uint8_t numOfGroups)
+{
+	
+}
+void
+WifiTxStatistics::NotifyDataSent(uint16_t length, uint32_t dataRate)
+{
+	m_currentSize = length;
+	m_currentRate = dataRate;
+}
+
+WifiTxStatistics::RATE_STAT::iterator
+WifiTxStatistics::FillCurrentStatPosition(uint16_t length, uint32_t dataRate)
+{
+	uint16_t group = (length/(m_maxLength/m_numOfGroups)+1)* (m_maxLength/m_numOfGroups);
+#if 0
+	for(RATE_LENGTH_STAT::iterator i = m_stats.begin(); i != m_stats.end(); i ++)
+		if(i->first == )
+#endif
+	RATE_LENGTH_STAT::iterator lengthPos = m_stats.find(group);
+	if(lengthPos == m_stats.end())
+	{
+		RATE_STAT newStat;
+		m_stats[group] = newStat;
+	}
+	lengthPos = m_stats.find(group);
+	NS_ASSERT(lengthPos != m_stats.end());
+	RATE_STAT::iterator ratePos = lengthPos->second.find(dataRate);
+	if(ratePos == lengthPos->second.end())
+	{
+		SIMPLE_STAT newStat;
+		newStat.packetsFailed =0;
+		newStat.packetsRetried = 0;
+		newStat.packetsAcked = 0;
+		newStat.rtsFailed = 0;
+		newStat.rtsRetried = 0;
+		newStat.rtsAcked = 0;
+		newStat.bytesFailed = 0;
+		newStat.bytesRetried = 0;
+		newStat.bytesAcked = 0;
+		lengthPos->second[dataRate] = newStat;
+	}
+	ratePos = lengthPos->second.find(dataRate);
+	NS_ASSERT(ratePos != lengthPos->second.end());
+	return  ratePos;
+}
+
+void
+WifiTxStatistics::NotifyDataFailed()
+{
+	RATE_STAT::iterator ratePos =  FillCurrentStatPosition(m_currentSize, m_currentRate);
+	ratePos->second.packetsFailed++;
+	ratePos->second.bytesFailed += m_currentSize;
+
+}
+
+void
+WifiTxStatistics::NotifyGotAck(uint32_t retryCounter)
+{
+	RATE_STAT::iterator ratePos =  FillCurrentStatPosition(m_currentSize, m_currentRate);
+	ratePos->second.packetsAcked++;
+	ratePos->second.packetsRetried += retryCounter;
+	ratePos->second.bytesAcked+= m_currentSize;
+	ratePos->second.bytesRetried += (m_currentSize*retryCounter);
+}
+
+void
+WifiTxStatistics::NotifyRtsSend(uint32_t rtsRate, uint32_t dataLength)
+{
+	m_currentSize = dataLength;
+	m_currentRate = rtsRate;
+}
+
+void
+WifiTxStatistics::NotifyRtsFailed()
+{
+	RATE_STAT::iterator ratePos =  FillCurrentStatPosition(m_currentSize, m_currentRate);
+	ratePos->second.rtsFailed++;
+	ratePos->second.bytesFailed += m_currentSize;
+}
+
+void
+WifiTxStatistics::NotifyRtsSuccess(uint32_t retryCounter)
+{
+	RATE_STAT::iterator ratePos =  FillCurrentStatPosition(m_currentSize, m_currentRate);
+	ratePos->second.rtsAcked++;
+	ratePos->second.rtsRetried += retryCounter;
+	ratePos->second.bytesAcked += m_currentSize;
+	ratePos->second.bytesRetried += (m_currentSize*retryCounter);
+}
+
+void
+WifiTxStatistics::ResetStatistics()
+{
+	for(RATE_LENGTH_STAT::iterator lengthPos = m_stats.begin(); lengthPos != m_stats.end(); lengthPos++)
+		lengthPos->second.clear();
+}
+#if 0
+WifiTxStatistics::SIMPLE_STAT
+WifiTxStatistics::GetTxStatCommon()
+{
+}
+
+WifiTxStatistics::RATE_STAT
+WifiTxStatistics::GetTxStatRate()
+{
+}
+
+WifiTxStatistics::LENGTH_STAT
+WifiTxStatistics::GetTxStatLength()
+{
+}
+#endif
+WifiTxStatistics::TX_STATISTICS
+WifiTxStatistics::GetTxStatRateLength()
+{
+	TX_STATISTICS retval;
+	retval.statistics = m_stats;
+	retval.lengthInterval = m_maxLength / m_numOfGroups;
+	retval.maxLength = m_maxLength;
+	return retval;
+}
+#if 0
+void
+WifiTxStatistics::Print()
+{
+	for(RATE_LENGTH_STAT::iterator lengthPos = m_stats.begin(); lengthPos != m_stats.end(); lengthPos++)
+	{
+		NS_LOG_UNCOND("\tGROUP = " <<lengthPos->first);
+		for(RATE_STAT::iterator ratePos = lengthPos->second.begin(); ratePos != lengthPos->second.end(); ratePos ++)
+		{
+			NS_LOG_UNCOND("Rate is "<<ratePos->first
+					<<": SUCCESS = "<<ratePos->second.packetsAcked
+					<<", RRETRY = " <<ratePos->second.packetsRetried
+					<<", FAILURE = "<<ratePos->second.packetsFailed);
+		}
+	}
+}
+#endif
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/tx-statistics.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,104 @@
+/* -*-  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 TX_STAT_H
+#define TX_STAT_H
+
+#include <map>
+#include <utility>
+#include "ns3/mac48-address.h"
+#include "ns3/packet.h"
+#include "ns3/object.h"
+#include "ns3/traced-value.h"
+#include "wifi-mode.h"
+
+namespace ns3 {
+	class WifiTxStatistics : public Object
+	{
+		public:
+			static TypeId		GetTypeId(void);
+			WifiTxStatistics();
+			~WifiTxStatistics();
+
+			struct TxStat
+			{
+				/**
+				 * Packet counters:
+				 */
+				uint32_t	packetsFailed;
+				uint32_t	packetsRetried;
+				uint32_t	packetsAcked;
+				/**
+				 * RTS counters:
+				 */
+				uint32_t	rtsFailed;
+				uint32_t	rtsRetried;
+				uint32_t	rtsAcked;
+				/**
+				 * Byte counters:
+				 */
+				uint64_t	bytesFailed;
+				uint64_t	bytesRetried;
+				uint64_t	bytesAcked;
+			};
+			typedef struct TxStat			SIMPLE_STAT;
+			typedef std::map<uint32_t, SIMPLE_STAT> RATE_STAT;
+#if 0
+			typedef	std::map<uint16_t, SIMPLE_STAT>	LENGTH_STAT;
+#endif
+			typedef std::map<uint16_t, RATE_STAT>	RATE_LENGTH_STAT;
+
+			void			SetLengthDivisionParams(uint16_t maxLength, uint8_t numOfGroups);
+
+			void			NotifyDataSent(uint16_t length, uint32_t dataRate);
+			void			NotifyDataFailed();
+			void			NotifyGotAck(uint32_t retryCounter);
+
+			void			NotifyRtsSend(uint32_t rtsRate, uint32_t dataLength);
+			void			NotifyRtsRetried();
+			void			NotifyRtsFailed();
+			void			NotifyRtsSuccess(uint32_t retryCounter);
+
+			void			ResetStatistics();
+#if 0
+			SIMPLE_STAT		GetTxStatCommon();
+			RATE_STAT		GetTxStatRate();
+			LENGTH_STAT		GetTxStatLength();
+#endif
+			typedef struct {
+				RATE_LENGTH_STAT	statistics;
+				uint16_t		lengthInterval;
+				uint16_t		maxLength;
+			} TX_STATISTICS;
+			TX_STATISTICS		GetTxStatRateLength();
+		private:
+			RATE_STAT::iterator	FillCurrentStatPosition(uint16_t length, uint32_t dataRate);
+			//DEBUG PURPOSE
+			//void			Print();
+			RATE_LENGTH_STAT	m_stats;
+			bool			m_isTx;
+			uint8_t			m_numOfGroups;
+			uint16_t		m_maxLength;
+			uint16_t		m_currentSize;
+			uint32_t		m_currentRate;
+	};
+} //namespace ns3
+#endif
--- a/src/devices/wifi/wifi-mac-header.cc	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/devices/wifi/wifi-mac-header.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -125,6 +125,13 @@
   m_ctrlType = TYPE_DATA;
   m_ctrlSubtype = 0;
 }
+void
+WifiMacHeader::SetMultihopAction (void)
+{
+ m_ctrlType = TYPE_MGT;
+ m_ctrlSubtype = 15;
+}
+
 void 
 WifiMacHeader::SetType (enum WifiMacType_e type)
 {
@@ -188,6 +195,9 @@
   case WIFI_MAC_MGT_DEAUTHENTICATION:
     m_ctrlType = TYPE_MGT;
     m_ctrlSubtype = 12;
+  case WIFI_MAC_MGT_MULTIHOP_ACTION:
+    m_ctrlType = TYPE_MGT;
+    m_ctrlSubtype = 15;
     break;
 
   case WIFI_MAC_DATA:
@@ -360,6 +370,9 @@
     case 12:
       return WIFI_MAC_MGT_DEAUTHENTICATION;
       break;
+   case 15:
+      return WIFI_MAC_MGT_MULTIHOP_ACTION;
+      break;
 
     }
     break;
@@ -553,6 +566,11 @@
 {
   return (GetType () == WIFI_MAC_MGT_DEAUTHENTICATION)?true:false;
 }
+bool
+WifiMacHeader::IsMultihopAction (void) const
+{
+  return (GetType () == WIFI_MAC_MGT_MULTIHOP_ACTION)?true:false;
+}
 
 
 uint16_t 
@@ -861,6 +879,7 @@
     case WIFI_MAC_QOSDATA_NULL:
     case WIFI_MAC_QOSDATA_NULL_CFPOLL:
     case WIFI_MAC_QOSDATA_NULL_CFACK_CFPOLL:
+    case WIFI_MAC_MGT_MULTIHOP_ACTION:
       break;
     }
 }
@@ -961,4 +980,338 @@
   return i.GetDistanceFrom (start);
 }
 
+/***********************************************************
+ * 	Here Mesh Mac Header functionality is defined.
+ ***********************************************************/
+TypeId 
+WifiMeshHeader::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::WifiMeshHeader")
+    .SetParent<Header> ()
+    .AddConstructor<WifiMeshHeader> ()
+    ;
+  return tid;
+}
+
+WifiMeshHeader::WifiMeshHeader()
+{
+	m_meshFlags = 0;
+}
+
+WifiMeshHeader::~WifiMeshHeader()
+{
+}
+
+TypeId 
+WifiMeshHeader::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+void
+WifiMeshHeader::SetAddr5 (Mac48Address address)
+{
+	m_addr5 = address;
+}
+
+void
+WifiMeshHeader::SetAddr6 (Mac48Address address)
+{
+	m_addr6 = address;
+}
+
+void
+WifiMeshHeader::SetAddr7 (Mac48Address address)
+{
+	m_addr7 = address;
+}
+
+Mac48Address
+WifiMeshHeader::GetAddr5 ()
+{
+	return m_addr5;
+}
+
+Mac48Address
+WifiMeshHeader::GetAddr6 ()
+{
+	return m_addr6;
+}
+
+Mac48Address
+WifiMeshHeader::GetAddr7 ()
+{
+	return m_addr7;
+}
+
+void
+WifiMeshHeader::SetMeshSeqno (uint32_t seqno)
+{
+	m_meshSeqno = seqno;
+}
+
+uint32_t
+WifiMeshHeader::GetMeshSeqno ()
+{
+	return m_meshSeqno;
+}
+
+void
+WifiMeshHeader::SetMeshTtl (uint8_t TTL)
+{
+	m_meshTtl = TTL;
+}
+
+uint8_t
+WifiMeshHeader::GetMeshTtl ()
+{
+	return m_meshTtl;
+}
+
+void
+WifiMeshHeader::SetAddressExt (uint8_t num_of_addresses)
+{
+	if (num_of_addresses > 3)
+		return;
+	m_meshFlags = MESH_AE_MASK| (num_of_addresses << MESH_AE_SHIFT);
+}
+
+uint8_t
+WifiMeshHeader::GetAddressExt ()
+{
+	return ((MESH_AE_MASK & m_meshFlags) >> MESH_AE_SHIFT);
+}
+
+
+uint32_t
+WifiMeshHeader::GetSerializedSize (void) const
+{
+	return 6 + ((MESH_AE_MASK & m_meshFlags) >> MESH_AE_SHIFT)*6;
+}
+
+void
+WifiMeshHeader::Serialize (Buffer::Iterator start) const
+{
+	Buffer::Iterator i = start;
+	i.WriteU8(m_meshFlags);
+	i.WriteU8(m_meshTtl);
+	i.WriteU32(m_meshSeqno);
+	uint8_t addresses_to_add = (m_meshFlags & MESH_AE_MASK) >> MESH_AE_SHIFT;
+	//Writing Address extensions:
+	if(addresses_to_add > 0)
+		WriteTo (i, m_addr5);
+	if(addresses_to_add > 1)
+		WriteTo (i, m_addr6);
+	if(addresses_to_add > 2)
+		WriteTo (i, m_addr7);
+}
+
+uint32_t
+WifiMeshHeader::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.ReadU32();
+	addresses_to_read = (m_meshFlags & MESH_AE_MASK) >> MESH_AE_SHIFT;
+	if(addresses_to_read > 0)
+		ReadFrom (i, m_addr5);
+	if(addresses_to_read > 1)
+		ReadFrom (i, m_addr6);
+	if(addresses_to_read > 2)
+		ReadFrom (i, m_addr7);
+	return i.GetDistanceFrom(start);
+}
+void
+WifiMeshHeader::Print (std::ostream &os) const
+{
+	os << "flags" << m_meshFlags
+		<< "ttl" << m_meshTtl
+		<< "seqno" << m_meshSeqno;
+}
+/**********************************************************
+ * 		MultihopActionFrame
+ **********************************************************/
+WifiMeshMultihopActionHeader::WifiMeshMultihopActionHeader ()
+{
+}
+
+WifiMeshMultihopActionHeader::~WifiMeshMultihopActionHeader ()
+{
+}
+
+void
+WifiMeshMultihopActionHeader::SetAction(
+		enum WifiMeshMultihopActionHeader::CategoryValue type,
+		WifiMeshMultihopActionHeader::ACTION_VALUE action)
+{
+	switch(type)
+	{
+		case MESH_PEER_LINK_MGT:
+			m_category = 4;
+			switch (action.peerLink)
+			{
+				case PEER_LINK_OPEN:
+					m_actionValue = 0;
+					break;
+				case PEER_LINK_CONFIRM:
+					m_actionValue = 1;
+					break;
+				case PEER_LINK_CLOSE:
+					m_actionValue = 2;
+					break;
+			};
+			break;
+		case MESH_LINK_METRIC:
+			m_category = 5;
+			break;
+		case MESH_PATH_SELECTION:
+			m_category = 6;
+			switch(action.pathSelection)
+			{
+				case PATH_REQUEST:
+					m_actionValue = 0;
+					break;
+				case PATH_REPLY:
+					m_actionValue = 1;
+					break;
+				case PATH_ERROR:
+					m_actionValue = 2;
+					break;
+				case ROOT_ANNOUNCEMENT:
+					m_actionValue = 3;
+					break;
+			};
+			break;
+		case MESH_INTERWORK_ACTION:
+			m_category = 7;
+			break;
+		case MESH_RESOURCE_COORDINATION:
+			m_category = 8;
+			break;
+	};
+}
+
+enum WifiMeshMultihopActionHeader::CategoryValue
+WifiMeshMultihopActionHeader::GetCategory()
+{
+	switch(m_category)
+	{
+		case 4:
+			return MESH_PEER_LINK_MGT;
+		case 5:
+			return MESH_LINK_METRIC;
+		case 6:
+			return MESH_PATH_SELECTION;
+		case 7:
+			return MESH_INTERWORK_ACTION;
+		case 8:
+			return MESH_RESOURCE_COORDINATION;
+		default:
+			NS_ASSERT(false);
+			return MESH_PEER_LINK_MGT;
+	}
+}
+
+WifiMeshMultihopActionHeader::ACTION_VALUE
+WifiMeshMultihopActionHeader::GetAction()
+{
+	ACTION_VALUE retval;
+	switch(m_category)
+	{
+		case 4:
+			//MESH_PEER_LINK_MGT;
+			switch(m_actionValue)
+			{
+				case 0:
+					retval.peerLink = PEER_LINK_OPEN;
+					return retval;
+				case 1:
+					retval.peerLink = PEER_LINK_CONFIRM;
+					return retval;
+				case 2:
+					retval.peerLink = PEER_LINK_CLOSE;
+					return retval;
+				default:
+					NS_ASSERT(false);
+					return retval;
+
+			}
+		case 5:
+			//MESH_LINK_METRIC;
+		case 6:
+			//MESH_PATH_SELECTION;
+			switch(m_actionValue)
+			{
+				case 0:
+					retval.pathSelection = PATH_REQUEST;
+					return retval;
+				case 1:
+					retval.pathSelection = PATH_REPLY;
+					return retval;
+				case 2:
+					retval.pathSelection = PATH_ERROR;
+					return retval;
+				case 3:
+					retval.pathSelection = ROOT_ANNOUNCEMENT;
+					return retval;
+				default:
+					NS_ASSERT(false);
+					return retval;
+			}
+
+		case 7:
+			//MESH_INTERWORK_ACTION;
+		case 8:
+			//MESH_RESOURCE_COORDINATION;
+		default:
+			NS_ASSERT(false);
+			return retval;
+	}
+}
+
+TypeId
+WifiMeshMultihopActionHeader::GetTypeId (void)
+{
+	static TypeId tid = TypeId ("ns3::WifiMeshMultihopActionHeader")
+		.SetParent<Header> ()
+		.AddConstructor<WifiMeshMultihopActionHeader> ()
+		;
+	return tid;
+}
+
+TypeId
+WifiMeshMultihopActionHeader::GetInstanceTypeId (void) const
+{
+	return GetTypeId();
+}
+
+void
+WifiMeshMultihopActionHeader::Print (std::ostream &os) const
+{
+}
+
+uint32_t
+WifiMeshMultihopActionHeader::GetSerializedSize (void) const
+{
+	return 2;
+}
+
+void
+WifiMeshMultihopActionHeader::Serialize (Buffer::Iterator start) const
+{
+	start.WriteU8(m_category);
+	start.WriteU8(m_actionValue);
+}
+
+uint32_t
+WifiMeshMultihopActionHeader::Deserialize (Buffer::Iterator start)
+{
+	Buffer::Iterator i = start;
+	m_category = i.ReadU8();
+	m_actionValue = i.ReadU8();
+	return i.GetDistanceFrom(start);
+}
+
 } // namespace ns3
--- a/src/devices/wifi/wifi-mac-header.h	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/devices/wifi/wifi-mac-header.h	Sat Feb 28 14:21:05 2009 +0300
@@ -44,6 +44,8 @@
   WIFI_MAC_MGT_PROBE_RESPONSE,
   WIFI_MAC_MGT_AUTHENTICATION,
   WIFI_MAC_MGT_DEAUTHENTICATION,
+//Mesh management frames:  
+  WIFI_MAC_MGT_MULTIHOP_ACTION,
 
   WIFI_MAC_DATA,
   WIFI_MAC_DATA_CFACK,
@@ -83,6 +85,7 @@
   void SetProbeResp (void);
   void SetBeacon (void);
   void SetTypeData (void);
+  void SetMultihopAction();
   void SetDsFrom (void);
   void SetDsNotFrom (void);
   void SetDsTo (void);
@@ -129,6 +132,7 @@
   bool IsDisassociation (void) const;
   bool IsAuthentication (void) const;
   bool IsDeauthentication (void) const;
+  bool IsMultihopAction(void) const;
   uint16_t GetRawDuration (void) const;
   Time GetDuration (void) const;
   uint16_t GetSequenceControl (void) const;
@@ -176,7 +180,120 @@
   uint8_t m_qosAckPolicy;
   uint16_t m_qosStuff;
 };
+class WifiMeshHeader : public Header //7.1.3.5b
+{
+	public:
+		WifiMeshHeader ();
+		~WifiMeshHeader ();
+		static TypeId GetTypeId (void);
+		virtual TypeId GetInstanceTypeId (void) const;
+		virtual void Print (std::ostream &os) const;
 
+		void			SetAddr5 (Mac48Address address);
+		void			SetAddr6 (Mac48Address address);
+		void			SetAddr7 (Mac48Address address);
+		Mac48Address		GetAddr5 ();
+		Mac48Address		GetAddr6 ();
+		Mac48Address		GetAddr7 ();
+
+		void			SetMeshSeqno (uint32_t seqno);
+		uint32_t		GetMeshSeqno ();
+
+		void			SetMeshTtl (uint8_t TTL);
+		uint8_t		GetMeshTtl ();
+
+#define MESH_AE_MASK	0xc0
+#define MESH_AE_SHIFT	6
+		void			SetAddressExt (uint8_t num_of_addresses);
+		uint8_t		GetAddressExt ();
+
+		virtual uint32_t	GetSerializedSize (void) 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_addr5;
+		Mac48Address	m_addr6;
+		Mac48Address	m_addr7;
+};
+class WifiMeshMultihopActionHeader : public Header //7.2.3.14
+{
+	//Multichop action frame consists of Mesh header, Action, and
+	//the last information. Mesh header is present within all data
+	//frames and multihop action frames, so Mesh header is a
+	//separate structure. Each MultihopAction frames (frames like
+	//PREQ, PREP and other) start form Category field and Action
+	//value field, so the Multihop Action Frame should containt
+	//three fields: Category, Action Value;
+	public:
+		WifiMeshMultihopActionHeader ();
+		~WifiMeshMultihopActionHeader ();
+		enum CategoryValue //table 7-24 staring from 4
+		{
+			MESH_PEER_LINK_MGT =4,
+			MESH_LINK_METRIC,
+			MESH_PATH_SELECTION,
+			MESH_INTERWORK_ACTION,
+			MESH_RESOURCE_COORDINATION,
+		};
+		enum PeerLinkMgtActionValue
+		{
+			PEER_LINK_OPEN = 0,
+			PEER_LINK_CONFIRM,
+			PEER_LINK_CLOSE,
+		};
+		enum LinkMetricActionValue
+		{
+			LINK_METRIC_REQUEST = 0,
+			LINK_METRIC_REPORT,
+		};
+		enum PathSelectionActionValue
+		{
+			PATH_REQUEST = 0,
+			PATH_REPLY,
+			PATH_ERROR,
+			ROOT_ANNOUNCEMENT,
+		};
+		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_ADJASTMENT_REQUEST,
+			MESH_CHANNEL_SWITCH_ANNOUNCEMENT,
+		};
+		typedef union
+		{
+			enum PeerLinkMgtActionValue		peerLink;
+			enum LinkMetricActionValue		linkMetrtic;
+			enum PathSelectionActionValue		pathSelection;
+			enum InterworkActionValue		interwork;
+			enum ResourceCoordinationActionValue	resourceCoordination;
+		} ACTION_VALUE;
+		void			SetAction(enum CategoryValue type,ACTION_VALUE action);
+		enum CategoryValue	GetCategory();
+		ACTION_VALUE		GetAction();
+		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);
+	private:
+		uint8_t	m_category;
+		uint8_t	m_actionValue;
+};
 } // namespace ns3
 
 
--- a/src/devices/wifi/wifi-remote-station-manager.cc	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/devices/wifi/wifi-remote-station-manager.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -422,7 +422,9 @@
   : m_state (BRAND_NEW),
     m_ssrc (0),
     m_slrc (0)
-{}
+{
+	m_txStat = CreateObject<WifiTxStatistics> ();
+}
 WifiRemoteStation::~WifiRemoteStation ()
 {}
 
@@ -543,7 +545,7 @@
 WifiMode 
 WifiRemoteStation::GetAckMode (WifiMode dataMode)
 {
-  return GetControlAnswerMode (dataMode);
+  return dataMode;
 }
 
 uint32_t 
@@ -572,12 +574,14 @@
 {
   if (GetManager ()->IsLowLatency ())
     {
+      m_txStat->NotifyDataSent(fullPacketSize, DoGetDataMode (fullPacketSize).GetDataRate());
       return DoGetDataMode (fullPacketSize);
     }
   TxModeTag tag;
   bool found;
   found = packet->FindFirstMatchingTag (tag);
   NS_ASSERT (found);
+  m_txStat->NotifyDataSent(fullPacketSize, tag.GetDataMode ().GetDataRate());
   return tag.GetDataMode ();
 }
 WifiMode 
@@ -585,12 +589,14 @@
 {
   if (GetManager ()->IsLowLatency ())
     {
+      m_txStat->NotifyDataSent(packet->GetSize() +36, DoGetRtsMode().GetDataRate());
       return DoGetRtsMode ();
     }
   TxModeTag tag;
   bool found;
   found = packet->FindFirstMatchingTag (tag);
   NS_ASSERT (found);
+  m_txStat->NotifyDataSent(packet->GetSize() +36, tag.GetRtsMode ().GetDataRate());
   return tag.GetRtsMode ();
 }
 
@@ -693,6 +699,7 @@
 void 
 WifiRemoteStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
 {
+  m_txStat->NotifyRtsSuccess(m_ssrc);
   m_ssrc = 0;
   DoReportRtsOk (ctsSnr, ctsMode, rtsSnr);
 }
@@ -700,6 +707,7 @@
 void 
 WifiRemoteStation::ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
 {
+  m_txStat->NotifyGotAck(m_slrc);
   m_slrc = 0;
   DoReportDataOk (ackSnr, ackMode, dataSnr);
 }
@@ -708,6 +716,7 @@
 WifiRemoteStation::ReportFinalRtsFailed (void)
 {
   m_ssrc = 0;
+  m_txStat->NotifyRtsFailed();
   DoReportFinalRtsFailed ();
 }
 
@@ -715,6 +724,7 @@
 WifiRemoteStation::ReportFinalDataFailed (void)
 {
   m_slrc = 0;
+  m_txStat->NotifyDataFailed();
   DoReportFinalDataFailed ();
 }
 
@@ -723,5 +733,16 @@
 {
   DoReportRxOk (rxSnr, txMode);
 }
+WifiTxStatistics::TX_STATISTICS
+WifiRemoteStation::GetTxStat()
+{
+	return m_txStat->GetTxStatRateLength();
+}
+void
+WifiRemoteStation::ResetTxStat()
+{
+	m_txStat->ResetStatistics();
+}
+
 } // namespace ns3
 
--- a/src/devices/wifi/wifi-remote-station-manager.h	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/devices/wifi/wifi-remote-station-manager.h	Sat Feb 28 14:21:05 2009 +0300
@@ -26,6 +26,7 @@
 #include "ns3/packet.h"
 #include "ns3/object.h"
 #include "ns3/traced-value.h"
+#include "ns3/tx-statistics.h"
 #include "wifi-mode.h"
 
 namespace ns3 {
@@ -257,6 +258,8 @@
    *          handshake.
    */
   WifiMode GetAckMode (WifiMode dataMode);
+  WifiTxStatistics::TX_STATISTICS GetTxStat();
+  void ResetTxStat();
 
 private:
   typedef std::vector<WifiMode> SupportedModes;
@@ -286,6 +289,7 @@
   SupportedModes m_modes;
   TracedValue<uint32_t> m_ssrc;
   TracedValue<uint32_t> m_slrc;
+  Ptr<WifiTxStatistics> m_txStat;
 };
 
 } // namespace ns3 
--- a/src/devices/wifi/wscript	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/devices/wifi/wscript	Sat Feb 28 14:21:05 2009 +0300
@@ -3,6 +3,7 @@
 def build(bld):
     obj = bld.create_ns3_module('wifi', ['node'])
     obj.source = [
+        'tx-statistics.cc',
         'propagation-delay-model.cc',
         'propagation-loss-model.cc',
         'jakes-propagation-loss-model.cc',
@@ -35,6 +36,16 @@
         'adhoc-wifi-mac.cc',
         'nqap-wifi-mac.cc',
         'nqsta-wifi-mac.cc',
+        'mesh-wifi-mac.cc',
+        'mesh-configuration-element.cc',
+        'mesh-wifi-beacon-timing-element.cc',
+        'dot11s-peer-management-element.cc',
+        'mesh-mgt-headers.cc',
+        'mesh-wifi-peer-manager.cc',
+        'mesh-wifi-rann-information-element.cc',
+        'mesh-wifi-preq-information-element.cc',
+        'mesh-wifi-perr-information-element.cc',
+        'mesh-wifi-prep-information-element.cc',
         'wifi-net-device.cc',
         'arf-wifi-manager.cc',
         'aarf-wifi-manager.cc',
@@ -44,10 +55,12 @@
         'rraa-wifi-manager.cc',
         'constant-rate-wifi-manager.cc',
         'wifi-test.cc',
+        'dot11s-parameters.cc',
         ]
     headers = bld.new_task_gen('ns3header')
     headers.module = 'wifi'
     headers.source = [
+        'tx-statistics.h',
         'propagation-delay-model.h',
         'propagation-loss-model.h',
         'jakes-propagation-loss-model.h',
@@ -73,10 +86,25 @@
         'adhoc-wifi-mac.h',
         'nqsta-wifi-mac.h',
         'nqap-wifi-mac.h',
+        'mesh-wifi-mac.h',
         'wifi-phy.h',
         'supported-rates.h',
+        'mgt-headers.h',
+        'status-code.h',
+        'capability-information.h',
+        'mesh-configuration-element.h',
+        'mesh-wifi-beacon-timing-element.h',
+        'dot11s-peer-management-element.h',
+        'mesh-mgt-headers.h', 
+        'mesh-wifi-peer-manager.h',
+        'mesh-wifi-rann-information-element.h',
+        'mesh-wifi-preq-information-element.h',
+        'mesh-wifi-perr-information-element.h',
+        'mesh-wifi-prep-information-element.h',
         'error-rate-model.h',
         'yans-error-rate-model.h',
+        'dot11s-codes.h',
+        'dot11s-parameters.h',
         ]
 
     obj = bld.create_ns3_program('wifi-phy-test',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/hwmp-helper.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,21 @@
+/* -*-  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>
+ */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/hwmp-helper.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,21 @@
+/* -*-  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>
+ */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/mesh-wifi-helper.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,220 @@
+/* -*-  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>
+ *          Evgeny Khorov <horov@frtk.ru>
+ */
+
+
+#include "mesh-wifi-helper.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/wifi-mac.h"
+#include "ns3/wifi-phy.h"
+#include "ns3/wifi-remote-station-manager.h"
+#include "ns3/wifi-channel.h"
+#include "ns3/yans-wifi-channel.h"
+#include "ns3/propagation-delay-model.h"
+#include "ns3/propagation-loss-model.h"
+#include "ns3/mobility-model.h"
+#include "ns3/log.h"
+#include "ns3/pcap-writer.h"
+#include "ns3/config.h"
+#include "ns3/simulator.h"
+#include "ns3/hwmp.h"
+
+NS_LOG_COMPONENT_DEFINE ("MeshWifiHelper");
+namespace ns3
+{
+
+MeshWifiHelper::MeshWifiHelper ()
+{
+	//m_deviceFactory.SetTypeId ("ns3::L2RoutingNetDevice");
+}
+
+MeshWifiHelper::~MeshWifiHelper ()
+{
+}
+
+void
+MeshWifiHelper::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
+MeshWifiHelper::SetMac (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_meshMac = ObjectFactory ();
+	m_meshMac.SetTypeId (type);
+	m_meshMac.Set (n0, v0);
+	m_meshMac.Set (n1, v1);
+	m_meshMac.Set (n2, v2);
+	m_meshMac.Set (n3, v3);
+	m_meshMac.Set (n4, v4);
+	m_meshMac.Set (n5, v5);
+	m_meshMac.Set (n6, v6);
+	m_meshMac.Set (n7, v7);
+}
+
+void
+MeshWifiHelper::SetL2RoutingProtocol(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,
+		std::string n8, const AttributeValue &v8,
+		std::string n9, const AttributeValue &v9)
+{
+	m_routingProtocol = ObjectFactory ();
+	m_routingProtocol.SetTypeId (type);
+	m_routingProtocol.Set (n0, v0);
+	m_routingProtocol.Set (n1, v1);
+	m_routingProtocol.Set (n2, v2);
+	m_routingProtocol.Set (n3, v3);
+	m_routingProtocol.Set (n4, v4);
+	m_routingProtocol.Set (n5, v5);
+	m_routingProtocol.Set (n6, v6);
+	m_routingProtocol.Set (n7, v7);
+}
+
+void
+MeshWifiHelper::SetL2RoutingNetDevice(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,
+		std::string n8, const AttributeValue &v8,
+		std::string n9, const AttributeValue &v9)
+{
+	m_deviceFactory = ObjectFactory ();
+	m_deviceFactory.SetTypeId (type);
+	m_deviceFactory.Set (n0, v0);
+	m_deviceFactory.Set (n1, v1);
+	m_deviceFactory.Set (n2, v2);
+	m_deviceFactory.Set (n3, v3);
+	m_deviceFactory.Set (n4, v4);
+	m_deviceFactory.Set (n5, v5);
+	m_deviceFactory.Set (n6, v6);
+	m_deviceFactory.Set (n7, v7);
+}
+
+void
+MeshWifiHelper::SetPeerLinkManager (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,
+		std::string n8, const AttributeValue &v8,
+		std::string n9, const AttributeValue &v9)
+{
+	m_peerManager = ObjectFactory ();
+	m_peerManager.SetTypeId (type);
+	m_peerManager.Set (n0, v0);
+	m_peerManager.Set (n1, v1);
+	m_peerManager.Set (n2, v2);
+	m_peerManager.Set (n3, v3);
+	m_peerManager.Set (n4, v4);
+	m_peerManager.Set (n5, v5);
+	m_peerManager.Set (n6, v6);
+	m_peerManager.Set (n7, v7);
+	m_peerManager.Set (n8, v8);
+	m_peerManager.Set (n9, v9);
+}
+
+NetDeviceContainer
+MeshWifiHelper::Install (const WifiPhyHelper &phyHelper, NodeContainer c, uint8_t numOfPorts) const
+{
+	NetDeviceContainer devices;
+	for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+	{
+		Ptr<Node> node = *i;
+		Ptr<L2RoutingNetDevice> virtualDevice = m_deviceFactory.Create<L2RoutingNetDevice> ();
+		Ptr<WifiPeerManager>pPeer = m_peerManager.Create<WifiPeerManager > ();
+		devices.Add (virtualDevice);
+		std::vector<Ptr<WifiNetDevice> > nodeDevices;
+		for (uint8_t k=0; k<numOfPorts; k++)
+		{
+			Ptr<WifiNetDevice> device = CreateObject<WifiNetDevice> ();
+			Ptr<MeshWifiMac> mac = m_meshMac.Create<MeshWifiMac> ();
+			Ptr<WifiRemoteStationManager> manager = m_stationManager.Create<WifiRemoteStationManager> ();
+			Ptr<WifiPhy> phy = phyHelper.Create (node, device);
+			mac->SetAddress (Mac48Address::Allocate ());
+			device->SetMac (mac);
+			device->SetPhy (phy);
+			device->SetRemoteStationManager (manager);
+			//mac ->SetPeerLinkManager (pPeer);
+			//create L2RoutingNetDevice and add WifiNetDevice to it
+			node->AddDevice(device);
+			nodeDevices.push_back(device);
+		}
+		node -> AddDevice(virtualDevice);
+		for (std::vector<Ptr<WifiNetDevice> > ::iterator iter=nodeDevices.begin();iter!=nodeDevices.end(); ++iter)
+			virtualDevice->AddPort(*iter);
+		// nodeDevice.pop_back()
+		pPeer->AttachPorts(nodeDevices);
+		Ptr<L2RoutingProtocol> routingProtocol = m_routingProtocol.Create <L2RoutingProtocol>();
+		virtualDevice->AttachProtocol(routingProtocol);
+		//hwmp->SetRoot(device->GetIfIndex(), Seconds(5));
+		nodeDevices.clear();
+	}
+	return devices;
+}
+
+NetDeviceContainer
+MeshWifiHelper::Install (const WifiPhyHelper &phy, Ptr<Node> node, uint8_t numOfPorts) const
+{
+	return Install (phy, NodeContainer (node), numOfPorts);
+}
+
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/mesh-wifi-helper.h	Sat Feb 28 14:21:05 2009 +0300
@@ -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>
+ *          Evgeny Khorov <horov@frtk.ru>
+ */
+
+
+#ifndef _MESHWIFIHELPER_H
+#define	_MESHWIFIHELPER_H
+
+#include "ns3/wifi-net-device.h"
+#include "ns3/l2-routing-net-device.h"
+#include "ns3/mesh-wifi-mac.h"
+#include "ns3/wifi-channel.h"
+#include "ns3/mesh-wifi-peer-manager.h"
+#include "wifi-helper.h"
+
+namespace ns3
+{
+	class WifiChannel;
+
+	class MeshWifiHelper
+	{
+		public:
+			MeshWifiHelper ();
+			virtual ~MeshWifiHelper ();
+
+			/**
+			 * \param type the type of peer manager to use.
+			 * \param n0 the name of the attribute to set in the peer manager.
+			 * \param v0 the value of the attribute to set in the peer manager.
+			 * etc.
+			 *
+			 */
+			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 ());
+
+			/**
+			 * \param type the type of ns3::WifiMac to create.
+			 * \param n0 the name of the attribute to set
+			 * \param v0 the value of the attribute to set
+			 *
+			 * All the attributes specified in this method should exist
+			 * in the requested mac.
+			 */
+			void SetMac (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 SetPeerLinkManager (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 (),
+					std::string n8 = "", const AttributeValue &v8 = EmptyAttributeValue (),
+					std::string n9 = "", const AttributeValue &v9 = EmptyAttributeValue ());
+			void SetL2RoutingProtocol(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 (),
+					std::string n8 = "", const AttributeValue &v8 = EmptyAttributeValue (),
+					std::string n9 = "", const AttributeValue &v9 = EmptyAttributeValue ());
+
+			void SetL2RoutingNetDevice(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 (),
+					std::string n8 = "", const AttributeValue &v8 = EmptyAttributeValue (),
+					std::string n9 = "", const AttributeValue &v9 = EmptyAttributeValue ());
+			NetDeviceContainer Install (const WifiPhyHelper &phyHelper, NodeContainer c, uint8_t numOfPorts) const;
+			NetDeviceContainer Install (const WifiPhyHelper &phy, Ptr<Node> node, uint8_t numOfPorts) const;
+		private:
+			ObjectFactory m_stationManager;
+			ObjectFactory m_meshMac;
+			ObjectFactory m_peerManager;
+			//L2routing:
+			ObjectFactory m_deviceFactory;
+			ObjectFactory m_routingProtocol;
+	};
+}//namespace ns3
+#endif	/* _MESHWIFIHELPER_H */
+
--- a/src/helper/wscript	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/helper/wscript	Sat Feb 28 14:21:05 2009 +0300
@@ -23,6 +23,8 @@
         'bridge-helper.cc',
         'yans-wifi-helper.cc',
         'v4ping-helper.cc',
+        'mesh-wifi-helper.cc',
+        'hwmp-helper.cc',
         ]
 
     headers = bld.new_task_gen('ns3header')
@@ -48,6 +50,8 @@
         'bridge-helper.h',
         'yans-wifi-helper.h',
         'v4ping-helper.h',
+        'mesh-wifi-helper.h',
+        'hwmp-helper.h',
         ]
 
     env = bld.env_of_name('default')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/l2-routing-protocol.cc	Sat Feb 28 14:21:05 2009 +0300
@@ -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
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+
+#include "ns3/object.h"
+#include "ns3/log.h"
+#include "l2-routing-protocol.h"
+
+NS_LOG_COMPONENT_DEFINE ("L2RoutingProtocol");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (L2RoutingProtocol);
+
+TypeId
+L2RoutingProtocol::GetTypeId (void)
+{
+	static TypeId tid = TypeId ("ns3::L2RoutingProtocol")
+		.SetParent<Object> ();
+	return tid;
+}
+
+L2RoutingProtocol::~L2RoutingProtocol ()
+{}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/l2-routing-protocol.h	Sat Feb 28 14:21:05 2009 +0300
@@ -0,0 +1,166 @@
+/* -*-  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 L2_ROUTING_PROTOCOL_H
+#define L2_ROUTING_PROTOCOL_H
+
+#include <list>
+#include <vector>
+#include <ostream>
+#include "ns3/nstime.h"
+#include "ns3/mac48-address.h"
+#include "ns3/net-device.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class Packet;
+/**
+ * \ingroup node
+ * \defgroup L2RoutingProtocol L2routingProtocol
+ */
+/**
+ * \ingroup L2RoutingProtocol
+ *
+ * \brief Base class for Layer 2 routing protocols
+ *
+ * \details Yhis class is an internal part of L2RoutingNetDevice class
+ * and this class implements interface between L2RoutingNetDevice and
+ * any protocol of MAC layer. This interface is similar to ipv4
+ * routiong protocol base class.
+ */
+class L2RoutingProtocol : public Object
+{
+	public:
+		static TypeId GetTypeId();
+		virtual ~L2RoutingProtocol();
+		/**
+		 * \brief Callback to be invoked when route discovery
+		 * procedure is completed
+		 * \param bool flag indicating whether a route was
+		 * actually found and all needed information is added
+		 * to the packet succesfully
+		 * \param Ptr<Packet> is packet, for which the route
+		 * was resolved
+		 * \attention All needed 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 L2RoutingNetDevice looks
+		 * like a pure packet with ethernet header (i.e data
+		 * +src +dst + protocol). All information needed to
+		 * L2RoutingNetDevice is outgoing port ID.
+		 * \param Mac48Address Source address of the packet
+		 * \param Mac48Address Destiation address of the
+		 * packet
+		 * \param uint16_t Ethernet 'Protocol' field - stored
+		 * in protocol, needed to form a proper MAC-layer
+		 * header.
+		 * \param uint32_t Output port
+		 */
+typedef Callback<
+	void,
+	bool,
+	Ptr<Packet>,
+	Mac48Address,
+	Mac48Address,
+	uint16_t,
+	uint32_t
+		>
+		RouteReplyCallback;
+		/**
+		 * \brief All packets must go through RequestRoute
+		 * \returns Can the route be discovered or not
+		 * \param sourceIface The incoming interface of the
+		 * packet
+		 * \param source Source address of the packet
+		 * \param destination Destination address of the
+		 * packet
+		 * \param packet The packet to be resolved (needed the
+		 * whole packet, because we can add tags or headers).
+		 * \param protocolType The protocol ID (must be stored
+		 * for route discovery time to form a proper MAC-layer
+		 * header).
+		 * \param routeReply Callback to be invoked after route
+		 * discovery procedure.
+		 */
+		virtual bool RequestRoute(
+				uint32_t		sourceIface,
+				const Mac48Address	source,
+				const Mac48Address	destination,
+				Ptr<Packet>		packet,
+				uint16_t		protocolType,
+				RouteReplyCallback	routeReply
+				) = 0;
+		/**
+		 * \brief Attaches ports to the L2RoutingProtocols,
+		 * \returns False if there are not proper devices (like
+		 * HWMP, which requires only WifiNetDevice and works
+		 * only above MeshWifiMac).
+		 * \param ports The array of ports.
+		 */
+		virtual bool AttachPorts(std::vector<Ptr<NetDevice> > ports) = 0;
+		/**
+		 * \brief L2Routing protocol must know the
+		 * L2RoutingNetDevice ID to determine packets as 'came
+		 * from upper layer' and 'received from network' (for
+		 * example, to manage TTL).
+		 * \param interface The interface ID of
+		 * L2RoutingNetDevice
+		 */
+		virtual void SetIfIndex(uint32_t interface) = 0;
+	protected:
+		struct QueuedPacket {
+			Ptr<Packet>	pkt;
+			Mac48Address	dst;
+			Mac48Address	src;
+			uint16_t	protocol;
+			uint32_t	inPort;
+			RouteReplyCallback reply;
+		};
+		/**
+		 * \brief Set Max queue size per destinztion
+		 * \details Routing Queue is implemented inside the
+		 * routing protocol and keeps one queue per
+		 * destination (to make it easier to find resolved and
+		 * timed out packets).
+		 * \param maxPacketsPerDestination Packets per
+		 * destination that can be stored inside protocol.
+		 */
+		virtual void SetMaxQueueSize(int maxPacketsPerDestination) = 0;
+		/**
+		 * \brief Queue packet with 'Ethernet header'
+		 * \returns false if the queue is full.
+		 */
+		virtual bool QueuePacket(struct QueuedPacket packet) = 0;
+		/**
+		 * \brief Deques packet with 'Ethernet header'
+		 * \returns Ptr<packet> (NULL if queue is empty), src,
+		 * dst, protocol ID, incoming port ID, and reply
+		 * callback
+		 * \param destination The destination address, which
+		 * identifyes queue.
+		 */
+		virtual struct QueuedPacket DequeuePacket(Mac48Address destination) = 0;
+};
+}//namespace ns3
+#endif
--- a/src/node/wscript	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/node/wscript	Sat Feb 28 14:21:05 2009 +0300
@@ -38,6 +38,7 @@
         'ipv6-address.cc',
         'ipv6-header.cc',
         'ipv4-raw-socket-factory.cc',
+        'l2-routing-protocol.cc',
         ]
 
     headers = bld.new_task_gen('ns3header')
@@ -77,4 +78,5 @@
         'ipv6-address.h',
         'ipv6-header.h',
         'ipv4-raw-socket-factory.h',
+        'l2-routing-protocol.h',
         ]
--- a/src/wscript	Wed Feb 25 12:27:00 2009 -0500
+++ b/src/wscript	Sat Feb 28 14:21:05 2009 +0300
@@ -34,6 +34,8 @@
     'helper',
     'contrib/stats',
     'applications/v4ping',
+    'devices/l2-routing/l2-routing-main',
+    'devices/l2-routing/l2-routing-hwmp',
     )
 
 def set_options(opt):