Merge 802.11s code.

This commit is contained in:
Andrey Mazo
2009-02-28 14:21:05 +03:00
parent fa47453c53
commit 82d09ba538
56 changed files with 9546 additions and 3 deletions

108
examples/mesh.cc Normal file
View File

@@ -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;
}

View File

@@ -120,6 +120,10 @@ def build(bld):
['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',

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1 @@
exec "`dirname "$0"`"/../../../../waf "$@"

View File

@@ -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',
]

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1 @@
exec "`dirname "$0"`"/../../../../waf "$@"

View File

@@ -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',
]

View File

@@ -161,6 +161,7 @@ private:
bool m_accessOngoing;
Ptr<const Packet> m_currentPacket;
WifiMacHeader m_currentHdr;
uint8_t m_currentRetry;
uint8_t m_fragmentNumber;
};

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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();
};
}

View File

@@ -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

View File

@@ -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;
};
}

View File

@@ -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

View File

@@ -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 ()
MgtProbeResponseHeader::~MgtProbeResponseHeader ()
{}
uint64_t
MgtProbeResponseHeader::GetTimestamp()
{
return m_timestamp;
}
Ssid
MgtProbeResponseHeader::GetSsid (void) const
{
@@ -198,7 +205,7 @@ uint32_t
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 @@ MgtProbeResponseHeader::Deserialize (Buffer::Iterator start)
//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

View File

@@ -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 @@ public:
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 @@ public:
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 @@ private:
};
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

View File

@@ -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

View File

@@ -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

View File

@@ -125,6 +125,13 @@ WifiMacHeader::SetTypeData (void)
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 @@ WifiMacHeader::SetType (enum WifiMacType_e type)
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 @@ WifiMacHeader::GetType (void) const
case 12:
return WIFI_MAC_MGT_DEAUTHENTICATION;
break;
case 15:
return WIFI_MAC_MGT_MULTIHOP_ACTION;
break;
}
break;
@@ -553,6 +566,11 @@ WifiMacHeader::IsDeauthentication (void) const
{
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 @@ WifiMacHeader::Print (std::ostream &os) const
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 @@ WifiMacHeader::Deserialize (Buffer::Iterator start)
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

View File

@@ -44,6 +44,8 @@ enum WifiMacType_e {
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 @@ public:
void SetProbeResp (void);
void SetBeacon (void);
void SetTypeData (void);
void SetMultihopAction();
void SetDsFrom (void);
void SetDsNotFrom (void);
void SetDsTo (void);
@@ -129,6 +132,7 @@ public:
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 @@ private:
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

View File

@@ -422,7 +422,9 @@ WifiRemoteStation::WifiRemoteStation ()
: m_state (BRAND_NEW),
m_ssrc (0),
m_slrc (0)
{}
{
m_txStat = CreateObject<WifiTxStatistics> ();
}
WifiRemoteStation::~WifiRemoteStation ()
{}
@@ -543,7 +545,7 @@ WifiRemoteStation::GetCtsMode (WifiMode rtsMode)
WifiMode
WifiRemoteStation::GetAckMode (WifiMode dataMode)
{
return GetControlAnswerMode (dataMode);
return dataMode;
}
uint32_t
@@ -572,12 +574,14 @@ WifiRemoteStation::GetDataMode (Ptr<const Packet> packet, uint32_t fullPacketSiz
{
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 @@ WifiRemoteStation::GetRtsMode (Ptr<const Packet> packet)
{
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 @@ WifiRemoteStation::ReportDataFailed (void)
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 @@ WifiRemoteStation::ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
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 @@ void
WifiRemoteStation::ReportFinalRtsFailed (void)
{
m_ssrc = 0;
m_txStat->NotifyRtsFailed();
DoReportFinalRtsFailed ();
}
@@ -715,6 +724,7 @@ void
WifiRemoteStation::ReportFinalDataFailed (void)
{
m_slrc = 0;
m_txStat->NotifyDataFailed();
DoReportFinalDataFailed ();
}
@@ -723,5 +733,16 @@ WifiRemoteStation::ReportRxOk (double rxSnr, WifiMode txMode)
{
DoReportRxOk (rxSnr, txMode);
}
WifiTxStatistics::TX_STATISTICS
WifiRemoteStation::GetTxStat()
{
return m_txStat->GetTxStatRateLength();
}
void
WifiRemoteStation::ResetTxStat()
{
m_txStat->ResetStatistics();
}
} // namespace ns3

View File

@@ -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 @@ public:
* handshake.
*/
WifiMode GetAckMode (WifiMode dataMode);
WifiTxStatistics::TX_STATISTICS GetTxStat();
void ResetTxStat();
private:
typedef std::vector<WifiMode> SupportedModes;
@@ -286,6 +289,7 @@ private:
SupportedModes m_modes;
TracedValue<uint32_t> m_ssrc;
TracedValue<uint32_t> m_slrc;
Ptr<WifiTxStatistics> m_txStat;
};
} // namespace ns3

View File

@@ -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 @@ def build(bld):
'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 @@ def build(bld):
'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 @@ def build(bld):
'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',

21
src/helper/hwmp-helper.cc Normal file
View File

@@ -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>
*/

21
src/helper/hwmp-helper.h Normal file
View File

@@ -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>
*/

View File

@@ -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

View File

@@ -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 */

View File

@@ -23,6 +23,8 @@ def build(bld):
'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 @@ def build(bld):
'bridge-helper.h',
'yans-wifi-helper.h',
'v4ping-helper.h',
'mesh-wifi-helper.h',
'hwmp-helper.h',
]
env = bld.env_of_name('default')

View File

@@ -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

View File

@@ -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

View File

@@ -38,6 +38,7 @@ def build(bld):
'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 @@ def build(bld):
'ipv6-address.h',
'ipv6-header.h',
'ipv4-raw-socket-factory.h',
'l2-routing-protocol.h',
]

View File

@@ -34,6 +34,8 @@ all_modules = (
'helper',
'contrib/stats',
'applications/v4ping',
'devices/l2-routing/l2-routing-main',
'devices/l2-routing/l2-routing-hwmp',
)
def set_options(opt):