diff --git a/examples/mesh.cc b/examples/mesh.cc new file mode 100644 index 000000000..6f9db0efe --- /dev/null +++ b/examples/mesh.cc @@ -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 + * Evgeny Khorov + */ + + +#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:"< + */ + + +#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 () + .AddConstructor (); + 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::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::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::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::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::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::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::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::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::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 +HwmpRtable::GetUnreachableDestinations(Mac48Address peerAddress, uint32_t port) +{ + std::vector retval; + for(std::map::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::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::iterator i = m_routes.find(destination); + if(i == m_routes.end()) + return 0; + return i->second.seqnum; +} + +std::vector +HwmpRtable::GetPrecursors(Mac48Address destination, uint32_t port) +{ + std::vector retval; + std::map::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::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 diff --git a/src/devices/l2-routing/l2-routing-hwmp/hwmp-rtable.h b/src/devices/l2-routing/l2-routing-hwmp/hwmp-rtable.h new file mode 100644 index 000000000..ea44e52c8 --- /dev/null +++ b/src/devices/l2-routing/l2-routing-hwmp/hwmp-rtable.h @@ -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 + */ + + +#ifndef HWMP_RTABLE_H +#define HWMP_RTABLE_H + +#include +#include +#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 + GetUnreachableDestinations(Mac48Address peerAddress, uint32_t port); + uint32_t + RequestSeqnum(Mac48Address dst); + std::vector + 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 precursors; + }; + struct ProactiveRoute + { + Mac48Address root; + Mac48Address retransmitter; + uint32_t metric; + Time whenExpire; + uint32_t seqnum; + std::vector 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 + m_routes; + std::map + m_roots; + }; +} //namespace ns3 +#endif diff --git a/src/devices/l2-routing/l2-routing-hwmp/hwmp-state.cc b/src/devices/l2-routing/l2-routing-hwmp/hwmp-state.cc new file mode 100644 index 000000000..48fca22f0 --- /dev/null +++ b/src/devices/l2-routing/l2-routing-hwmp/hwmp-state.cc @@ -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 + */ + + +#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 () + .AddConstructor () + ; + 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 cb) +{ + m_requestRouteCallback = cb; +} + +void +HwmpState::SetRequestRootPathCallback( + Callback cb) +{ + m_requestRootPathCallback = cb; +} + +//Setting MAC +void +HwmpState::SetMac(Ptr 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 cb + ) +{ + m_routingInfoCallback = cb; +} + +void +HwmpState::SetRetransmittersOfPerrCallback( + Callback, std::vector, 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, "<GetOriginatorAddress() == m_address); + NS_LOG_DEBUG("add a destination "<AddDestinationAddressElement(false, false, dst, 0); //DO = 0, RF = 0 + } +} +void +HwmpState::SendPathError(std::vector destinations) +{ + std::vector 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::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::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 "< > destinations = preq.GetDestinationList (); + for(std::vector >::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::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 "< 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 "< + */ + + +#ifndef HWMP_STATE_H +#define HWMP_STATE_H +#include +#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 cb); + void SetRequestRootPathCallback( + Callback 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 + failedDestinations; + uint32_t dsn; + Time lifetime; + enum InfoType type; + } INFO; + void SetRoutingInfoCallback( + Callback cb + ); + void SetRetransmittersOfPerrCallback( + Callback, std::vector, uint32_t> cb); + void RequestDestination(Mac48Address dest); + void SendPathError(std::vector destinations); + void SetAssociatedIfaceId(uint32_t interface); + uint32_t + GetAssociatedIfaceId(); + //Mac interaction: + void SetMac(Ptr mac); + void SetSendPreqCallback( + Callback cb); + void SetSendPrepCallback( + Callback cb); + void SetSendPerrCallback( + Callback > 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 + 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::iterator + m_myPreq; + //HWMP interaction callbacks: + Callback + m_routingInfoCallback; + Callback, std::vector, uint32_t> + m_retransmittersOfPerrCallback; + Callback + m_requestRouteCallback; + Callback + m_requestRootPathCallback; + //Mac interaction callbacks: + Callback + m_preqCallback; + Callback + m_prepCallback; + Callback > + 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 + m_dsnDatabase; + std::map + 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 + m_myPerrReceivers; + void AddPerrReceiver(Mac48Address receiver); + EventId m_perrTimer; + void SendOnePerr(); + //Configurable parameters: + uint8_t m_maxTtl; + }; +} //namespace ns3 +#endif diff --git a/src/devices/l2-routing/l2-routing-hwmp/hwmp.cc b/src/devices/l2-routing/l2-routing-hwmp/hwmp.cc new file mode 100644 index 000000000..2f0b777e7 --- /dev/null +++ b/src/devices/l2-routing/l2-routing-hwmp/hwmp.cc @@ -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 + * Aleksey Kovalenko + */ + + +#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 () + .AddConstructor () + ; + 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 () + .AddConstructor(); + return tid; +} +Hwmp::Hwmp() +{ + m_maxTtl = 32; + m_broadcastPerr = false; + m_rtable = CreateObject (); +} + +Hwmp::~Hwmp() +{ +} + +void +Hwmp::DoDispose() +{ + for(std::map::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 >::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, + 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::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 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 > ports) +{ + for(std::vector >::iterator i = ports.begin(); i != ports.end(); i++) + { + //Checking netdevice: + const WifiNetDevice * wifiNetDev = dynamic_cast (PeekPointer (*i)); + if(wifiNetDev == NULL) + return false; + MeshWifiMac * meshWifiMac = dynamic_cast (PeekPointer (wifiNetDev->GetMac())); + if(meshWifiMac == NULL) + return false; + //Adding HWMP-state + Ptr hwmpState = CreateObject (); + 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 >::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 >::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 >::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 >::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 >::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 >::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 "<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"< 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 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 +Hwmp::GetRetransmittersForFailedDestinations(std::vector failedDest, uint32_t port) +{ + std::vector retransmitters; + if(m_broadcastPerr) + retransmitters.push_back(Mac48Address::GetBroadcast()); + else + for(unsigned int i = 0; i< failedDest.size(); i ++) + { + std::vector 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 in this structure is NULL when queue is empty + std::map, 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::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::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::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 diff --git a/src/devices/l2-routing/l2-routing-hwmp/hwmp.h b/src/devices/l2-routing/l2-routing-hwmp/hwmp.h new file mode 100644 index 000000000..a73c4e489 --- /dev/null +++ b/src/devices/l2-routing/l2-routing-hwmp/hwmp.h @@ -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 + * Aleksey Kovalenko + */ + + +#ifndef HWMP_H +#define HWMP_H +#include +#include +#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, + uint16_t protocolType, + L2RoutingProtocol::RouteReplyCallback + routeReply + ); + bool AttachPorts(std::vector >); + 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 > + m_rqueue; + //devices and HWMP states: + enum DeviceState { + ENABLED, + DISABLED + }; + enum DeviceMode { + REACTIVE, + PROACTIVE, + ROOT + }; + std::vector + m_states; + std::vector + m_modes; + std::vector > + m_hwmpStates; + //Routing table: + Ptr + 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 > + m_requestCallback; + /** + * \brief Callback that shall be executed when + * need to send Path error + * \param std::vector is the + * list of unreachable destinations + * \param std::vector is + * receivers of PERR + */ + std::vector > > + m_pathErrorCallback; + void StartPathErrorProcedure( + std::vector 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 + GetRetransmittersForFailedDestinations( + std::vector 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 + 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 + m_timeoutDatabase; + /** + * Configurable parameters: + */ + uint8_t m_maxTtl; + bool m_broadcastPerr; + }; +} //namespace ns3 +#endif diff --git a/src/devices/l2-routing/l2-routing-hwmp/waf b/src/devices/l2-routing/l2-routing-hwmp/waf new file mode 100644 index 000000000..0ca1fc3f4 --- /dev/null +++ b/src/devices/l2-routing/l2-routing-hwmp/waf @@ -0,0 +1 @@ +exec "`dirname "$0"`"/../../../../waf "$@" diff --git a/src/devices/l2-routing/l2-routing-hwmp/wscript b/src/devices/l2-routing/l2-routing-hwmp/wscript new file mode 100644 index 000000000..a7cc524a1 --- /dev/null +++ b/src/devices/l2-routing/l2-routing-hwmp/wscript @@ -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', + ] diff --git a/src/devices/l2-routing/l2-routing-main/l2-routing-net-device.cc b/src/devices/l2-routing/l2-routing-main/l2-routing-net-device.cc new file mode 100644 index 000000000..af99a56d0 --- /dev/null +++ b/src/devices/l2-routing/l2-routing-main/l2-routing-net-device.cc @@ -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 + */ + + +#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 () + .AddConstructor () + ; + return tid; +} + + +L2RoutingNetDevice::L2RoutingNetDevice () +{ + NS_LOG_FUNCTION_NOARGS (); + m_channel = CreateObject (); +} + +L2RoutingNetDevice::~L2RoutingNetDevice() +{ + NS_LOG_FUNCTION_NOARGS (); +} + + void +L2RoutingNetDevice::DoDispose () +{ + NS_LOG_FUNCTION_NOARGS (); + for (std::vector< Ptr >::iterator iter = m_ports.begin (); iter != m_ports.end (); iter++) + *iter = 0; + m_ports.clear (); + m_node = 0; + NetDevice::DoDispose (); + +} + + void +L2RoutingNetDevice::ReceiveFromDevice (Ptr incomingPort, Ptr 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 inport, Ptr 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 +L2RoutingNetDevice::GetPort (uint32_t n) const +{ + NS_ASSERT(m_ports.size () > n); + return m_ports[n]; +} + +void +L2RoutingNetDevice::AddPort (Ptr 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 +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 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, 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, 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 +L2RoutingNetDevice::GetNode (void) const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_node; +} + + + void +L2RoutingNetDevice::SetNode (Ptr 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 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, + 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 >::iterator i = m_ports.begin(); i!= m_ports.end(); i++) + (*i) -> SendFrom(packet, src, dst, protocol); +} + +} // namespace ns3 diff --git a/src/devices/l2-routing/l2-routing-main/l2-routing-net-device.h b/src/devices/l2-routing/l2-routing-main/l2-routing-net-device.h new file mode 100644 index 000000000..a09ef125b --- /dev/null +++ b/src/devices/l2-routing/l2-routing-main/l2-routing-net-device.h @@ -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 + */ + + +#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 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 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 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 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, const Address& dest, uint16_t protocolNumber); + virtual bool SendFrom (Ptr packet, const Address& source, const Address& dest, uint16_t protocolNumber); + virtual Ptr GetNode (void) const; + virtual void SetNode (Ptr 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 protocol); + protected: + /** + * \brief This is similar to BridgeNetDevice + * method + */ + void ReceiveFromDevice (Ptr device, Ptr packet, uint16_t protocol, + Address const &source, Address const &destination, PacketType packetType); + /** + * \brief This is similar to BridgeNetDevice + * method + */ + void Forward (Ptr incomingPort, Ptr 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, + Mac48Address src, + Mac48Address dst, + uint16_t protocol, + uint32_t outPort + ); + private: + NetDevice::ReceiveCallback + m_rxCallback; + NetDevice::PromiscReceiveCallback + m_promiscRxCallback; + Mac48Address m_address; + Ptr m_node; + std::string m_name; + std::vector< Ptr > + m_ports; + uint32_t m_ifIndex; + uint16_t m_mtu; + Ptr + m_channel; + Callback< + bool, + uint32_t, + Mac48Address, + Mac48Address, + Ptr, + uint16_t, + L2RoutingProtocol::RouteReplyCallback> + m_requestRoute; + //What we give to L2Routing + L2RoutingProtocol::RouteReplyCallback + m_myResponse; + }; +} //namespace ns3 +#endif diff --git a/src/devices/l2-routing/l2-routing-main/waf b/src/devices/l2-routing/l2-routing-main/waf new file mode 100644 index 000000000..0ca1fc3f4 --- /dev/null +++ b/src/devices/l2-routing/l2-routing-main/waf @@ -0,0 +1 @@ +exec "`dirname "$0"`"/../../../../waf "$@" diff --git a/src/devices/l2-routing/l2-routing-main/wscript b/src/devices/l2-routing/l2-routing-main/wscript new file mode 100644 index 000000000..a6cfbd3ab --- /dev/null +++ b/src/devices/l2-routing/l2-routing-main/wscript @@ -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', + ] diff --git a/src/devices/wifi/dca-txop.h b/src/devices/wifi/dca-txop.h index 7765520b2..3f588e1a5 100644 --- a/src/devices/wifi/dca-txop.h +++ b/src/devices/wifi/dca-txop.h @@ -161,6 +161,7 @@ private: bool m_accessOngoing; Ptr m_currentPacket; WifiMacHeader m_currentHdr; + uint8_t m_currentRetry; uint8_t m_fragmentNumber; }; diff --git a/src/devices/wifi/dot11s-codes.h b/src/devices/wifi/dot11s-codes.h new file mode 100644 index 000000000..43171b3e6 --- /dev/null +++ b/src/devices/wifi/dot11s-codes.h @@ -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 + * Kirill Andreev + */ + + +#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 diff --git a/src/devices/wifi/dot11s-parameters.cc b/src/devices/wifi/dot11s-parameters.cc new file mode 100644 index 000000000..18f23cc4e --- /dev/null +++ b/src/devices/wifi/dot11s-parameters.cc @@ -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 + * Kirill Andreev + */ + + +#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); + +} diff --git a/src/devices/wifi/dot11s-parameters.h b/src/devices/wifi/dot11s-parameters.h new file mode 100644 index 000000000..c9e01bfd2 --- /dev/null +++ b/src/devices/wifi/dot11s-parameters.h @@ -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 + * Kirill Andreev + */ + + +#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 diff --git a/src/devices/wifi/dot11s-peer-management-element.cc b/src/devices/wifi/dot11s-peer-management-element.cc new file mode 100644 index 000000000..843fddb61 --- /dev/null +++ b/src/devices/wifi/dot11s-peer-management-element.cc @@ -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 + * Aleksey Kovalenko + */ + + +#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 diff --git a/src/devices/wifi/dot11s-peer-management-element.h b/src/devices/wifi/dot11s-peer-management-element.h new file mode 100644 index 000000000..ff8e1fd58 --- /dev/null +++ b/src/devices/wifi/dot11s-peer-management-element.h @@ -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 + * Aleksey Kovalenko + */ + + +#ifndef MESH_PEER_MAN_ELEMENT +#define MESH_PEER_MAN_ELEMENT + +#include +#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 + diff --git a/src/devices/wifi/mesh-configuration-element.cc b/src/devices/wifi/mesh-configuration-element.cc new file mode 100644 index 000000000..4eef36a8b --- /dev/null +++ b/src/devices/wifi/mesh-configuration-element.cc @@ -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 + * Aleksey Kovalenko + */ + + +#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< + * Aleksey Kovalenko + */ + + +#ifndef MESH_CONFIGURATION_H +#define MESH_CONFIGURATION_H + +#include +#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 diff --git a/src/devices/wifi/mesh-mgt-headers.cc b/src/devices/wifi/mesh-mgt-headers.cc new file mode 100644 index 000000000..570531d52 --- /dev/null +++ b/src/devices/wifi/mesh-mgt-headers.cc @@ -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 + * Yana Podkosova + * Aleksey Kovalenko + */ + + +#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
() + .AddConstructor () + ; + 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 + + diff --git a/src/devices/wifi/mesh-mgt-headers.h b/src/devices/wifi/mesh-mgt-headers.h new file mode 100644 index 000000000..4097e9765 --- /dev/null +++ b/src/devices/wifi/mesh-mgt-headers.h @@ -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 + * Yana Podkosova + * Aleksey Kovalenko + */ + + +#ifndef MESH_MGT_HEADERS_H +#define MESH_MGT_HEADERS_H + +#include + +#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 + + diff --git a/src/devices/wifi/mesh-wifi-beacon-timing-element.cc b/src/devices/wifi/mesh-wifi-beacon-timing-element.cc new file mode 100644 index 000000000..968d3e20a --- /dev/null +++ b/src/devices/wifi/mesh-wifi-beacon-timing-element.cc @@ -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 + */ + + +#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; + Ptrnew_element = Create(); + 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 new_element = Create(); + 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 diff --git a/src/devices/wifi/mesh-wifi-beacon-timing-element.h b/src/devices/wifi/mesh-wifi-beacon-timing-element.h new file mode 100644 index 000000000..83d1ca1ba --- /dev/null +++ b/src/devices/wifi/mesh-wifi-beacon-timing-element.h @@ -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 + */ + + +#ifndef WIFI_TIMING_ELEMENT_H +#define WIFI_TIMING_ELEMENT_H + +#include +#include "ns3/buffer.h" +#include "ns3/nstime.h" +#include +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 WifiBeaconTimingElementPointer; +typedef std::list 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 diff --git a/src/devices/wifi/mesh-wifi-mac.cc b/src/devices/wifi/mesh-wifi-mac.cc new file mode 100644 index 000000000..4dd1d929b --- /dev/null +++ b/src/devices/wifi/mesh-wifi-mac.cc @@ -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 + * Ivan Pustogarov + * Evgeny Khorov + */ + + +#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 () + .AddConstructor () + .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 (); + m_low->SetRxCallback (MakeCallback (&MacRxMiddle::Receive, m_rxMiddle)); + + m_dcfManager = new DcfManager (); + m_dcfManager->SetupLowListener (m_low); + + m_beaconDca = CreateObject (); + 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 (); + 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 (); + 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 phy) +{ + NS_LOG_FUNCTION (this << phy); + m_phy = phy; + m_dcfManager->SetupPhyListener (phy); + m_low->SetPhy (phy); +} + +void +MeshWifiMac::SetWifiRemoteStationManager (Ptr 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 manager) +{ + m_peerManager = manager; +} + +void +MeshWifiMac::Enqueue (Ptr packet, Mac48Address to, Mac48Address from) +{ + NS_LOG_FUNCTION (this << packet << to << from); + ForwardDown (packet, from, to); +} + +void +MeshWifiMac::Enqueue (Ptr 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, Mac48Address, Mac48Address> upCallback) +{ + NS_LOG_FUNCTION (this); + m_upCallback = upCallback; +} + +void +MeshWifiMac::SetLinkUpCallback (Callback linkUp) +{ + NS_LOG_FUNCTION (this); + if (!linkUp.IsNull ()) + { + linkUp (); + } +} + +void +MeshWifiMac::SetLinkDownCallback (Callback 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, Mac48Address src, Mac48Address dst) +{ + NS_LOG_FUNCTION (this << packet << src); + m_upCallback (packet, src, dst); +} + +void +MeshWifiMac::ForwardDown (Ptr packet, Mac48Address from, Mac48Address to) +{ + //TODO:Classify and queue + WifiMacHeader hdr; + Ptr 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 = "<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 = Create (); + + 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, WifiMacHeader const *hdr) +{ + if (hdr->IsBeacon ()) + { + MgtMeshBeaconHeader beacon; + Mac48Address from = hdr->GetAddr2(); + packet->RemoveHeader (beacon); + NS_LOG_DEBUG("Beacon received from "<GetAddr2()<< + " to "<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="<GetAddr3()<< + ", sa="<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 = Create (); + //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 = Create (); + 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 = Create (); + 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 receivers) +{ + NS_ASSERT(receivers.size()!=0); + Ptr packet = Create (); + 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 "< packet, const WifiMacHeader hdr) +{ + m_VO->Queue(packet, hdr); +} +void +MeshWifiMac::SetPreqReceivedCallback( + Callback cb) +{ + m_preqReceived = cb; +} + +void +MeshWifiMac::SetPrepReceivedCallback( + Callback cb) +{ + m_prepReceived = cb; +} + +void +MeshWifiMac::SetPerrReceivedCallback( + Callback cb) +{ + m_perrReceived = cb; +} + +void +MeshWifiMac::SetPeerStatusCallback( + Callback 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 "<first + <<": SUCCESS = "<second.packetsAcked + <<", RRETRY = " <second.packetsRetried + <<", FAILURE = "<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 "<ResetTxStat(); + NS_ASSERT(metric !=0); + return metric; +} + +} // namespace ns3 diff --git a/src/devices/wifi/mesh-wifi-mac.h b/src/devices/wifi/mesh-wifi-mac.h new file mode 100644 index 000000000..d949da392 --- /dev/null +++ b/src/devices/wifi/mesh-wifi-mac.h @@ -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 + * Evgeny Khorov + */ + + +#ifndef MAC_HIGH_MESH_H +#define MAC_HIGH_MESH_H + +#include +#include +#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 phy); + virtual void SetWifiRemoteStationManager (Ptr stationManager); + virtual void Enqueue (Ptr packet, Mac48Address to, Mac48Address from); + virtual void Enqueue (Ptr packet, Mac48Address to); + virtual bool SupportsSendFrom (void) const; + virtual void SetForwardUpCallback (Callback, Mac48Address, Mac48Address> upCallback); + virtual void SetLinkUpCallback (Callback linkUp); + virtual void SetLinkDownCallback (Callback 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 manager); + virtual void SetPreqReceivedCallback( + Callback 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 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 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 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 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, WifiMacHeader const *hdr); + virtual void ForwardUp (Ptr packet, Mac48Address src, Mac48Address dst); + void ForwardDown( + Ptr 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, const WifiMacHeader hdr); + void SetBeaconGeneration (bool enable); + bool GetBeaconGeneration (void) const; + SupportedRates GetSupportedRates (void) const; + virtual void DoDispose (void); + + Ptr m_BE; + Ptr m_BK; + Ptr m_VI; + Ptr m_VO; + Ptr m_beaconDca; + Ptr m_stationManager; + Ptr m_phy; + Callback, Mac48Address, Mac48Address> + m_upCallback; + Time m_beaconInterval; + Time m_randomStart; + + DcfManager * m_dcfManager; + MacRxMiddle * m_rxMiddle; + Ptr 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 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 + m_preqReceived; + Callback + m_prepReceived; + Callback + m_perrReceived; + Callback + 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 + m_metricDatabase; + }; + +} // namespace ns3 + + +#endif /* MAC_HIGH_MESH_H */ diff --git a/src/devices/wifi/mesh-wifi-peer-manager.cc b/src/devices/wifi/mesh-wifi-peer-manager.cc new file mode 100644 index 000000000..69d81f8c4 --- /dev/null +++ b/src/devices/wifi/mesh-wifi-peer-manager.cc @@ -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 + * Aleksey Kovalenko + * Ivan Pustogarov + * Evgeny Khorov + */ + + +#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 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 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 "<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 () + .AddConstructor () + //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 () + ) + //maximum number of peer links. + .AddAttribute ("MaxNumberOfPeerLinks", + "Maximum number of peer links ", + UintegerValue (32), + MakeUintegerAccessor (&WifiPeerManager::m_maxNumberOfPeerLinks), + MakeUintegerChecker () + ); + 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 >::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 >::iterator i = port->second.begin(); i!= port->second.end(); i++) + { + if((*i)->GetPeerAddress() == peerAddress) + { + (*i)->SetBeaconTimingElement(beaconTiming); + (*i)->SetBeaconInformation(lastBeacon, beaconInterval); + return; + } + } + Ptr new_descriptor = + AddDescriptor(portAddress, peerAddress, Simulator::Now(), beaconInterval); + new_descriptor->SetBeaconTimingElement(beaconTiming); +} + + bool +WifiPeerManager::AttachPorts(std::vector > ports) +{ + NS_ASSERT(ports.size()!=0); + for(std::vector >::iterator i = ports.begin(); i != ports.end(); i++) + { + MeshWifiMac * meshWifiMac = dynamic_cast (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 > 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 >::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 >::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()); + Ptrnew_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 >::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 >::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 >::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 >::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 >::iterator i = port->second.begin(); i!= port->second.end(); i++) + if((*i)->GetPeerAddress() == addr) + return_val = (*i)->GetBeaconTimingElement(); + return return_val; + + +} +Ptr +WifiPeerManager::AddDescriptor( + Mac48Address portAddress, + Mac48Address peerAddress, + Time lastBeacon, + Time beaconInterval) +{ + Ptr new_descriptor = Create(); + 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 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 +WifiPeerManager::GetNeighbourAddressList(Mac48Address portAddress, Mac48Address peerAddress) +{ + PeerDescriptorsMap::iterator port = m_peerDescriptors.find(portAddress); + NS_ASSERT(port!= m_peerDescriptors.end()); + std::vector return_value; + for(std::vector >::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 >::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 >::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 diff --git a/src/devices/wifi/mesh-wifi-peer-manager.h b/src/devices/wifi/mesh-wifi-peer-manager.h new file mode 100644 index 000000000..61c5fbe95 --- /dev/null +++ b/src/devices/wifi/mesh-wifi-peer-manager.h @@ -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 + * Aleksey Kovalenko + * Ivan Pustogarov + * Evgeny Khorov + */ + + +#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 + +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 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 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 m_mac; + Callback + m_linkStatusCallback; + }; + + class WifiPeerManager : public Object + { + public: + WifiPeerManager(); + WifiPeerManager(Ptr 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 + GetNeighbourAddressList(Mac48Address portAddress, Mac48Address peerAddress); + bool AttachPorts(std::vector >); + //void SetMac(Ptr 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 >, std::less > + PeerDescriptorsMap; + typedef std::map,std::less > MeshMacMap; + typedef std::map > BeaconInfoMap; + + //Ptr 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 + 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 diff --git a/src/devices/wifi/mesh-wifi-perr-information-element.cc b/src/devices/wifi/mesh-wifi-perr-information-element.cc new file mode 100644 index 000000000..deb7eb68b --- /dev/null +++ b/src/devices/wifi/mesh-wifi-perr-information-element.cc @@ -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 + * Kirill Andreev + */ + + +#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 (); + 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 +WifiPerrInformationElement::GetAddressUnitVector() +{ + return m_addressUnits; +} +void +WifiPerrInformationElement::DeleteAddressUnit(Mac48Address address) +{ + for(std::vector::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 + diff --git a/src/devices/wifi/mesh-wifi-perr-information-element.h b/src/devices/wifi/mesh-wifi-perr-information-element.h new file mode 100644 index 000000000..d71559c6d --- /dev/null +++ b/src/devices/wifi/mesh-wifi-perr-information-element.h @@ -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 + * Kirill Andreev + */ + + +#ifndef PERR_INFORMATION_ELEMENT_H +#define PERR_INFORMATION_ELEMENT_H + +#include +#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 + GetAddressUnitVector(); + void DeleteAddressUnit(Mac48Address address); + void ResetPerr(); + private: + uint8_t m_numOfDest; + std::vector + m_addressUnits; +}; + +} +#endif diff --git a/src/devices/wifi/mesh-wifi-prep-information-element.cc b/src/devices/wifi/mesh-wifi-prep-information-element.cc new file mode 100644 index 000000000..2ce9ad126 --- /dev/null +++ b/src/devices/wifi/mesh-wifi-prep-information-element.cc @@ -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 + * Kirill Andreev + */ + + +#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 (); + 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 diff --git a/src/devices/wifi/mesh-wifi-prep-information-element.h b/src/devices/wifi/mesh-wifi-prep-information-element.h new file mode 100644 index 000000000..66d628f6d --- /dev/null +++ b/src/devices/wifi/mesh-wifi-prep-information-element.h @@ -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 + * Kirill Andreev + */ + + +#ifndef WIFI_PREP_INFORMATION_ELEMENT_H +#define WIFI_PREP_INFORMATION_ELEMENT_H + + +#include +#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 + diff --git a/src/devices/wifi/mesh-wifi-preq-information-element.cc b/src/devices/wifi/mesh-wifi-preq-information-element.cc new file mode 100644 index 000000000..716472818 --- /dev/null +++ b/src/devices/wifi/mesh-wifi-preq-information-element.cc @@ -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 + * Kirill Andreev + */ + + +#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 (); + 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 >::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 new_element = Create(); + 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 > +WifiPreqInformationElement::GetDestinationList() +{ + return m_destinations; +} +void +WifiPreqInformationElement::AddDestinationAddressElement( + bool doFlag, bool rfFlag, + Mac48Address dest_address, + uint32_t dest_seq_number + ) +{ + for(std::vector >::iterator i = m_destinations.begin(); i!=m_destinations.end(); i++ ) + if((*i)->GetDestinationAddress() == dest_address) + return; + Ptrnew_element = Create(); + 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 >::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 >::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(); +}; + +} diff --git a/src/devices/wifi/mesh-wifi-preq-information-element.h b/src/devices/wifi/mesh-wifi-preq-information-element.h new file mode 100644 index 000000000..ddc7af268 --- /dev/null +++ b/src/devices/wifi/mesh-wifi-preq-information-element.h @@ -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 + * Kirill Andreev + */ + + +#ifndef WIFI_PREQ_INFORMATION_ELEMENT_H +#define WIFI_PREQ_INFORMATION_ELEMENT_H + +#include +#include "ns3/node.h" +#include "ns3/buffer.h" +#include "ns3/mac48-address.h" +#include "ns3/header.h" +#include +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 > 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 > + 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 + diff --git a/src/devices/wifi/mesh-wifi-rann-information-element.cc b/src/devices/wifi/mesh-wifi-rann-information-element.cc new file mode 100644 index 000000000..eea19ced1 --- /dev/null +++ b/src/devices/wifi/mesh-wifi-rann-information-element.cc @@ -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 + * Kirill Andreev + */ + + +#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 (); + 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; +}; + +} + diff --git a/src/devices/wifi/mesh-wifi-rann-information-element.h b/src/devices/wifi/mesh-wifi-rann-information-element.h new file mode 100644 index 000000000..d0bb8fa5d --- /dev/null +++ b/src/devices/wifi/mesh-wifi-rann-information-element.h @@ -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 + * Kirill Andreev + */ + + +#ifndef RANN_INFORMATION_ELEMENT_H +#define RANN_INFORMATION_ELEMENT_H + + +#include +#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 diff --git a/src/devices/wifi/mgt-headers.cc b/src/devices/wifi/mgt-headers.cc index eccb71aa6..6b5969151 100644 --- a/src/devices/wifi/mgt-headers.cc +++ b/src/devices/wifi/mgt-headers.cc @@ -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 diff --git a/src/devices/wifi/mgt-headers.h b/src/devices/wifi/mgt-headers.h index 45996600e..c99a62f96 100644 --- a/src/devices/wifi/mgt-headers.h +++ b/src/devices/wifi/mgt-headers.h @@ -21,11 +21,14 @@ #define MGT_HEADERS_H #include +#include #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 diff --git a/src/devices/wifi/tx-statistics.cc b/src/devices/wifi/tx-statistics.cc new file mode 100644 index 000000000..6393c806c --- /dev/null +++ b/src/devices/wifi/tx-statistics.cc @@ -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 + */ + + +#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 () + .AddConstructor (); + 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 = " <first); + for(RATE_STAT::iterator ratePos = lengthPos->second.begin(); ratePos != lengthPos->second.end(); ratePos ++) + { + NS_LOG_UNCOND("Rate is "<first + <<": SUCCESS = "<second.packetsAcked + <<", RRETRY = " <second.packetsRetried + <<", FAILURE = "<second.packetsFailed); + } + } +} +#endif +} //namespace ns3 diff --git a/src/devices/wifi/tx-statistics.h b/src/devices/wifi/tx-statistics.h new file mode 100644 index 000000000..5c62d9cc7 --- /dev/null +++ b/src/devices/wifi/tx-statistics.h @@ -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 + */ + + +#ifndef TX_STAT_H +#define TX_STAT_H + +#include +#include +#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 RATE_STAT; +#if 0 + typedef std::map LENGTH_STAT; +#endif + typedef std::map 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 diff --git a/src/devices/wifi/wifi-mac-header.cc b/src/devices/wifi/wifi-mac-header.cc index 057e3a875..3dc8e8c9c 100644 --- a/src/devices/wifi/wifi-mac-header.cc +++ b/src/devices/wifi/wifi-mac-header.cc @@ -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
() + .AddConstructor () + ; + 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
() + .AddConstructor () + ; + 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 diff --git a/src/devices/wifi/wifi-mac-header.h b/src/devices/wifi/wifi-mac-header.h index 01498364a..324c316d4 100644 --- a/src/devices/wifi/wifi-mac-header.h +++ b/src/devices/wifi/wifi-mac-header.h @@ -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 diff --git a/src/devices/wifi/wifi-remote-station-manager.cc b/src/devices/wifi/wifi-remote-station-manager.cc index 296a28e7b..b06725248 100644 --- a/src/devices/wifi/wifi-remote-station-manager.cc +++ b/src/devices/wifi/wifi-remote-station-manager.cc @@ -422,7 +422,9 @@ WifiRemoteStation::WifiRemoteStation () : m_state (BRAND_NEW), m_ssrc (0), m_slrc (0) -{} +{ + m_txStat = CreateObject (); +} 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 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 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 diff --git a/src/devices/wifi/wifi-remote-station-manager.h b/src/devices/wifi/wifi-remote-station-manager.h index 00e23f485..c67afc3a7 100644 --- a/src/devices/wifi/wifi-remote-station-manager.h +++ b/src/devices/wifi/wifi-remote-station-manager.h @@ -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 SupportedModes; @@ -286,6 +289,7 @@ private: SupportedModes m_modes; TracedValue m_ssrc; TracedValue m_slrc; + Ptr m_txStat; }; } // namespace ns3 diff --git a/src/devices/wifi/wscript b/src/devices/wifi/wscript index fb4016c14..23bcaf869 100644 --- a/src/devices/wifi/wscript +++ b/src/devices/wifi/wscript @@ -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', diff --git a/src/helper/hwmp-helper.cc b/src/helper/hwmp-helper.cc new file mode 100644 index 000000000..1f8be12f2 --- /dev/null +++ b/src/helper/hwmp-helper.cc @@ -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 + */ + + diff --git a/src/helper/hwmp-helper.h b/src/helper/hwmp-helper.h new file mode 100644 index 000000000..1f8be12f2 --- /dev/null +++ b/src/helper/hwmp-helper.h @@ -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 + */ + + diff --git a/src/helper/mesh-wifi-helper.cc b/src/helper/mesh-wifi-helper.cc new file mode 100644 index 000000000..dc1ce52b9 --- /dev/null +++ b/src/helper/mesh-wifi-helper.cc @@ -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 + * Evgeny Khorov + */ + + +#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 = *i; + Ptr virtualDevice = m_deviceFactory.Create (); + PtrpPeer = m_peerManager.Create (); + devices.Add (virtualDevice); + std::vector > nodeDevices; + for (uint8_t k=0; k device = CreateObject (); + Ptr mac = m_meshMac.Create (); + Ptr manager = m_stationManager.Create (); + Ptr 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 > ::iterator iter=nodeDevices.begin();iter!=nodeDevices.end(); ++iter) + virtualDevice->AddPort(*iter); + // nodeDevice.pop_back() + pPeer->AttachPorts(nodeDevices); + Ptr routingProtocol = m_routingProtocol.Create (); + virtualDevice->AttachProtocol(routingProtocol); + //hwmp->SetRoot(device->GetIfIndex(), Seconds(5)); + nodeDevices.clear(); + } + return devices; +} + +NetDeviceContainer +MeshWifiHelper::Install (const WifiPhyHelper &phy, Ptr node, uint8_t numOfPorts) const +{ + return Install (phy, NodeContainer (node), numOfPorts); +} + +} //namespace ns3 diff --git a/src/helper/mesh-wifi-helper.h b/src/helper/mesh-wifi-helper.h new file mode 100644 index 000000000..cbdabe6f6 --- /dev/null +++ b/src/helper/mesh-wifi-helper.h @@ -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 + * Evgeny Khorov + */ + + +#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, 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 */ + diff --git a/src/helper/wscript b/src/helper/wscript index 79fe4abe5..3bb9616a9 100644 --- a/src/helper/wscript +++ b/src/helper/wscript @@ -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') diff --git a/src/node/l2-routing-protocol.cc b/src/node/l2-routing-protocol.cc new file mode 100644 index 000000000..ac19dc0dd --- /dev/null +++ b/src/node/l2-routing-protocol.cc @@ -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 + */ + + +#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 (); + return tid; +} + +L2RoutingProtocol::~L2RoutingProtocol () +{} + +} // namespace ns3 diff --git a/src/node/l2-routing-protocol.h b/src/node/l2-routing-protocol.h new file mode 100644 index 000000000..511136e1c --- /dev/null +++ b/src/node/l2-routing-protocol.h @@ -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 + */ + + +#ifndef L2_ROUTING_PROTOCOL_H +#define L2_ROUTING_PROTOCOL_H + +#include +#include +#include +#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 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, + 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, + 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 > 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 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 (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 diff --git a/src/node/wscript b/src/node/wscript index cf318b0f2..640abceca 100644 --- a/src/node/wscript +++ b/src/node/wscript @@ -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', ] diff --git a/src/wscript b/src/wscript index 7977217a1..694bbdb6c 100644 --- a/src/wscript +++ b/src/wscript @@ -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):