diff --git a/src/devices/mesh/802.11s/ie-dot11s-beacon-timing.h b/src/devices/mesh/802.11s/ie-dot11s-beacon-timing.h index d0630e9d1..93511a9e8 100644 --- a/src/devices/mesh/802.11s/ie-dot11s-beacon-timing.h +++ b/src/devices/mesh/802.11s/ie-dot11s-beacon-timing.h @@ -28,6 +28,7 @@ #include "ns3/nstime.h" #include "ns3/dot11s-codes.h" #include "ns3/wifi-information-element.h" + namespace ns3 { /** * \ingroup dot11s diff --git a/src/devices/mesh/802.11s/peer-link.cc b/src/devices/mesh/802.11s/peer-link.cc new file mode 100644 index 000000000..cbe7611fd --- /dev/null +++ b/src/devices/mesh/802.11s/peer-link.cc @@ -0,0 +1,569 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Kirill Andreev + * Aleksey Kovalenko + * Pavel Boyko + */ + +#include "peer-link.h" +#include "ns3/log.h" +#include "ns3/uinteger.h" + +NS_LOG_COMPONENT_DEFINE ("Dot11sPeerManagementProtocol"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED(PeerLink); + +TypeId +PeerLink::GetTypeId() +{ + static TypeId tid = TypeId ("ns3::PeerLink") + .SetParent () + .AddConstructor () + .AddAttribute ("RetryTimeout", "Retry timeout", + TimeValue (TimeValue (MicroSeconds (40 * 1024))), + MakeTimeAccessor (&PeerLink::m_retryTimeout), + MakeTimeChecker () + ) + .AddAttribute ("HoldingTimeout", "Holding timeout", + TimeValue (TimeValue (MicroSeconds (40 * 1024))), + MakeTimeAccessor (&PeerLink::m_holdingTimeout), + MakeTimeChecker () + ) + .AddAttribute ("ConfirmTimeout", "Confirm timeout", + TimeValue (TimeValue (MicroSeconds (40 * 1024))), + MakeTimeAccessor (&PeerLink::m_confirmTimeout), + MakeTimeChecker () + ) + .AddAttribute ("MaxRetries", "Maximum number of retries", + UintegerValue (4), + MakeUintegerAccessor (&PeerLink::m_maxRetries), + MakeUintegerChecker () + ) + .AddAttribute ("MaxBeaconLoss", "Maximum number of lost beacons before link will be closed", + UintegerValue (3), + MakeUintegerAccessor (&PeerLink::m_maxBeaconLoss), + MakeUintegerChecker () + ); + return tid; +} + +//----------------------------------------------------------------------------- +// PeerLink public interface +//----------------------------------------------------------------------------- +PeerLink::PeerLink (): + m_localLinkId (0), + m_peerLinkId (0), + m_state (IDLE), + m_retryCounter (0) +{ +} + +void +PeerLink::SetPeerAddress (Mac48Address macaddr) +{ + m_peerAddress = macaddr; +} + +void +PeerLink::SetLocalAddress (Mac48Address macaddr) +{ + m_localAddress = macaddr; +} + +void +PeerLink::SetLocalLinkId (uint16_t id) +{ + m_localLinkId = id; +} + +void +PeerLink::SetLocalAid (uint16_t aid) +{ + m_assocId = aid; +} + +void +PeerLink::SetBeaconInformation (Time lastBeacon, Time beaconInterval) +{ + m_lastBeacon = lastBeacon; + m_beaconInterval = beaconInterval; + m_beaconLossTimer.Cancel (); + Time delay = Seconds(beaconInterval.GetSeconds() * m_maxBeaconLoss); + NS_ASSERT (delay.GetMicroSeconds() != 0); + m_beaconLossTimer = Simulator::Schedule (delay, &PeerLink::BeaconLoss, this); +} + +void +PeerLink::MLMESetSignalStatusCallback (PeerLink::SignalStatusCallback cb) +{ + m_linkStatusCallback = cb; +} + +void +PeerLink::BeaconLoss () +{ + StateMachine (CNCL); +} + +void +PeerLink::SetBeaconTimingElement (IeDot11sBeaconTiming beaconTiming) +{ + m_beaconTiming = beaconTiming; +} + +Mac48Address +PeerLink::GetPeerAddress () const +{ + return m_peerAddress; +} + +Mac48Address +PeerLink::GetLocalAddress () const +{ + return m_localAddress; +} + +uint16_t +PeerLink::GetLocalAid () const +{ + return m_assocId; +} + +Time +PeerLink::GetLastBeacon () const +{ + return m_lastBeacon; +} + +Time +PeerLink::GetBeaconInterval () const +{ + return m_beaconInterval; +} + +IeDot11sBeaconTiming +PeerLink::GetBeaconTimingElement () const +{ + return m_beaconTiming; +} + +void +PeerLink::ClearTimingElement () +{ + m_beaconTiming.ClearTimingElement (); +} + +void PeerLink::MLMECancelPeerLink (dot11sReasonCode reason) +{ + StateMachine (CNCL,reason); +} + +void PeerLink::MLMEPassivePeerLinkOpen () +{ + StateMachine (PASOPN); +} + +void PeerLink::MLMEActivePeerLinkOpen () +{ + StateMachine (ACTOPN); +} + +void PeerLink::MLMEPeeringRequestReject () +{ + StateMachine (REQ_RJCT, REASON11S_PEER_LINK_CANCELLED); +} + +void PeerLink::Close (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 PeerLink::OpenAccept (uint16_t localLinkId, IeDot11sConfiguration conf) +{ + if (m_peerLinkId == 0) + m_peerLinkId = localLinkId; + m_configuration = conf; + StateMachine (OPN_ACPT); +} + +void PeerLink::OpenReject (uint16_t localLinkId, IeDot11sConfiguration conf,dot11sReasonCode reason) +{ + if ( m_peerLinkId == 0) + m_peerLinkId = localLinkId; + m_configuration = conf; + StateMachine (OPN_RJCT, reason); +} + +void +PeerLink::ConfirmAccept (uint16_t localLinkId, uint16_t peerLinkId, uint16_t peerAid, IeDot11sConfiguration 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 +PeerLink::ConfirmReject (uint16_t localLinkId, uint16_t peerLinkId, + IeDot11sConfiguration 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 +PeerLink::LinkIsEstab () const +{ + return (m_state == ESTAB); +} + +bool +PeerLink::LinkIsIdle () const +{ + return (m_state == IDLE); +} +//----------------------------------------------------------------------------- +// Private +//----------------------------------------------------------------------------- +void +PeerLink::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 (REASON11S_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 (REASON11S_MESH_MAX_RETRIES); + SetHoldingTimer (); + break; + case CNCL: + m_state = HOLDING; + ClearRetryTimer (); + SendPeerLinkClose (REASON11S_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 PeerLink::SendPeerLinkOpen () +{ + IeDot11sPeerManagement peerElement; + peerElement.SetPeerOpen (m_localLinkId); + //NS_ASSERT (m_mac != NULL); + //m_mac->SendPeerLinkOpen (peerElement, m_peerAddress); +} + +void PeerLink::SendPeerLinkConfirm () +{ + IeDot11sPeerManagement peerElement; + peerElement.SetPeerConfirm (m_localLinkId, m_peerLinkId); + //m_mac->SendPeerLinkConfirm (peerElement, m_peerAddress, m_assocId); +} + +void PeerLink::SetHoldingTimer () +{ + m_holdingTimer = Simulator::Schedule (m_holdingTimeout, &PeerLink::HoldingTimeout, this); +} + +void PeerLink::HoldingTimeout () +{ + StateMachine (TOH); +} + +void PeerLink::SetRetryTimer () +{ + m_retryTimer = Simulator::Schedule (m_retryTimeout, &PeerLink::RetryTimeout, this); +} + +void PeerLink::RetryTimeout () +{ + if ( m_retryCounter < m_maxRetries) + StateMachine (TOR1); + else + StateMachine (TOR2); +} + +void PeerLink::SetConfirmTimer () +{ + m_confirmTimer = Simulator::Schedule (m_confirmTimeout, &PeerLink::ConfirmTimeout, this); +} + +void PeerLink::ConfirmTimeout () +{ + StateMachine (TOC); +} + +} \ No newline at end of file diff --git a/src/devices/mesh/802.11s/peer-link.h b/src/devices/mesh/802.11s/peer-link.h new file mode 100644 index 000000000..5aa52cef9 --- /dev/null +++ b/src/devices/mesh/802.11s/peer-link.h @@ -0,0 +1,249 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2009 IITP RAS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Kirill Andreev + * Aleksey Kovalenko + */ + +#ifndef PEERLLINK_H_ +#define PEERLLINK_H_ + +#include "ns3/object.h" +#include "ns3/nstime.h" +#include "ns3/callback.h" +#include "ns3/mac48-address.h" +#include "ns3/simulator.h" +#include "ie-dot11s-beacon-timing.h" +#include "ie-dot11s-peer-management.h" +#include "ie-dot11s-configuration.h" + +namespace ns3 { +/** + * \ingroup dot11s + * + * \brief Peer link model for 802.11s Peer Management protocol + */ +class PeerLink : public Object +{ +public: + /// Support object system + static TypeId GetTypeId(); + /// C-tor create empty link + PeerLink (); + + /// Process beacon received from peer + void SetBeaconInformation (Time lastBeacon, Time BeaconInterval); + /** + * \brief Method used to detecet peer link changes + * + * \param bool if true - opened new link, if false - link closed + */ + void SetLinkStatusCallback (Callback cb); + /** + * \name Peer link geeters/setters + * \{ + */ + void SetPeerAddress (Mac48Address macaddr); + 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 (IeDot11sBeaconTiming beaconTiming); + void SetPeerLinkDescriptorElement (IeDot11sPeerManagement peerLinkElement); + Mac48Address GetPeerAddress () const; + Mac48Address GetLocalAddress () const; + uint16_t GetLocalAid () const; + Time GetLastBeacon () const; + Time GetBeaconInterval () const; + IeDot11sBeaconTiming GetBeaconTimingElement ()const; + IeDot11sPeerManagement GetPeerLinkDescriptorElement ()const; + void ClearTimingElement (); + //\} + + /** + * \name MLME + * \{ + */ + /// MLME-CancelPeerLink.request + void MLMECancelPeerLink (dot11sReasonCode reason); + /// MLME-PassivePeerLinkOpen.request + void MLMEPassivePeerLinkOpen (); + /// MLME-ActivePeerLinkOpen.request + void MLMEActivePeerLinkOpen (); + /// MLME-PeeringRequestReject + void MLMEPeeringRequestReject (); + /// Callback type for MLME-SignalPeerLinkStatus event + typedef Callback SignalStatusCallback; + /// Set callback + void MLMESetSignalStatusCallback (SignalStatusCallback); + //\} + + /** + * \name Link response to received management frames + * + * \attention In all this methods {local/peer}LinkID correspond to _peer_ station, as written in + * received frame, e.g. I am peerLinkID and peer link is localLinkID . + * + * TODO is that clear? + * + * \{ + */ + /// Close link + void Close (uint16_t localLinkID, uint16_t peerLinkID, dot11sReasonCode reason); + /// Accept open link + void OpenAccept (uint16_t localLinkId, IeDot11sConfiguration conf); + /// Reject open link + void OpenReject (uint16_t localLinkId, IeDot11sConfiguration conf, dot11sReasonCode reason); + /// Confirm accept + void ConfirmAccept ( + uint16_t localLinkId, + uint16_t peerLinkId, + uint16_t peerAid, + IeDot11sConfiguration conf + ); + /// Confirm reject + void ConfirmReject ( + uint16_t localLinkId, + uint16_t peerLinkId, + IeDot11sConfiguration conf, + dot11sReasonCode reason + ); + //\} + + /// True if link is established + bool LinkIsEstab () const; + /// True if link is idle. Link can be deleted in this state + bool LinkIsIdle () const; + +private: + /// Peer link states, see 802.11s draft 11B.3.3.1 + enum PeerState { + IDLE, + LISTEN, + OPN_SNT, + CNF_RCVD, + OPN_RCVD, + ESTAB, + HOLDING, + }; + /// Peer link events, see 802.11s draft 11B.3.3.2 + enum PeerEvent + { + CNCL, ///< MLME-CancelPeerLink + PASOPN, ///< MLME-PassivePeerLinkOpen + ACTOPN, ///< MLME-ActivePeerLinkOpen + CLS_ACPT, ///< PeerLinkClose_Accept + OPN_ACPT, ///< PeerLinkOpen_Accept + OPN_RJCT, ///< PeerLinkOpen_Reject + REQ_RJCT, ///< PeerLinkOpenReject by internal reason + CNF_ACPT, ///< PeerLinkConfirm_Accept + CNF_RJCT, ///< PeerLinkConfirm_Reject + TOR1, ///< Timeout of retry timer + TOR2, ///< also timeout of retry timer + TOC, ///< Timeout of confirm timer + TOH, ///< Timeout of holding (gracefull closing) timer + }; + +private: + /// State transition + void StateMachine (PeerEvent event, dot11sReasonCode = REASON11S_RESERVED); + + /** + * \name Event handlers + * \{ + */ + void ClearRetryTimer (); + void ClearConfirmTimer (); + void ClearHoldingTimer (); + void SetHoldingTimer (); + void SetRetryTimer (); + void SetConfirmTimer (); + //\} + + /** + * \name Work with management frames + * \{ + */ + void SendPeerLinkClose (dot11sReasonCode reasoncode); + void SendPeerLinkOpen (); + void SendPeerLinkConfirm (); + //\} + + /** + * \name Timeout handlers + * \{ + */ + void HoldingTimeout (); + void RetryTimeout (); + void ConfirmTimeout (); + //\} + +private: + /// Peer address + Mac48Address m_peerAddress; + /// My own address + Mac48Address m_localAddress; + /// My ID of this link + uint16_t m_localLinkId; + /// Peer ID of this link + uint16_t m_peerLinkId; + /// My association ID + uint16_t m_assocId; + /// Assoc Id assigned to me by peer + uint16_t m_peerAssocId; + + /// When last beacon was sent (TODO or received?) + Time m_lastBeacon; + /// Current beacon interval on corresponding interface + Time m_beaconInterval; + + /// Current state + PeerState m_state; + /// Mesh interface configuration + IeDot11sConfiguration m_configuration; + + // State is a bitfield as defined as follows: + // This are states for a given + IeDot11sBeaconTiming m_beaconTiming; + + /** + * \name Timers & counters used for internal state transitions + * \{ + */ + Time m_retryTimeout; + EventId m_retryTimer; + Time m_holdingTimeout; + EventId m_holdingTimer; + Time m_confirmTimeout; + EventId m_confirmTimer; + uint16_t m_maxRetries; + uint16_t m_retryCounter; + EventId m_beaconLossTimer; + uint16_t m_maxBeaconLoss; + //\} + + /// ? + void BeaconLoss (); + + /// How to report my status change + SignalStatusCallback m_linkStatusCallback; +}; + +} + +#endif /* PEERLLINK_H_ */ \ No newline at end of file diff --git a/src/devices/mesh/802.11s/wscript b/src/devices/mesh/802.11s/wscript index fbd154429..733327e24 100644 --- a/src/devices/mesh/802.11s/wscript +++ b/src/devices/mesh/802.11s/wscript @@ -13,6 +13,7 @@ def build(bld): 'peer-manager-plugin.cc', 'peer-manager-protocol.cc', 'dot11s-helper.cc', + 'peer-link.cc', ] headers = bld.new_task_gen('ns3header') headers.module = '802.11s' @@ -27,6 +28,7 @@ def build(bld): 'peer-manager-protocol.h', 'peer-manager-plugin.h', 'dot11s-helper.h', + 'peer-link.h', ] # obj = bld.create_ns3_program('wifi-phy-test',