Files
unison/src/wimax/model/ss-link-manager.cc
Stefano Avallone 8adca5d42d Fix misuse of Create<>() function
If Create<>() is used to create an object of an Object subclass,
attributes are not initialized.
2025-06-13 13:27:40 +00:00

494 lines
14 KiB
C++

/*
* Copyright (c) 2007,2008,2009 INRIA, UDcast
*
* SPDX-License-Identifier: GPL-2.0-only
*
* Authors: Jahanzeb Farooq <jahanzeb.farooq@sophia.inria.fr>
* Mohamed Amine Ismail <amine.ismail@sophia.inria.fr>
* <amine.ismail@UDcast.com>
*/
#include "ss-link-manager.h"
#include "burst-profile-manager.h"
#include "service-flow-manager.h"
#include "ns3/enum.h"
#include "ns3/log.h"
#include "ns3/node.h"
#include "ns3/packet.h"
#include "ns3/pointer.h"
#include "ns3/simulator.h"
#include <cstdint>
namespace ns3
{
NS_LOG_COMPONENT_DEFINE("SSLinkManager");
NS_OBJECT_ENSURE_REGISTERED(SSLinkManager);
TypeId
SSLinkManager::GetTypeId()
{
static TypeId tid = TypeId("ns3::SSLinkManager").SetParent<Object>().SetGroupName("Wimax");
return tid;
}
SSLinkManager::SSLinkManager(Ptr<SubscriberStationNetDevice> ss)
: m_ss(ss),
m_rangingStatus(WimaxNetDevice::RANGING_STATUS_EXPIRED),
m_bsEirp(65535),
m_eirXPIrMax(65535),
m_pTxIrMax(0),
m_initRangOppNumber(0),
m_contentionRangingRetries(0),
m_rngReqFrameNumber(0),
m_dlChnlNr(0),
m_frequency(0),
m_rangingIntervalFound(false),
m_nrRngReqsSent(0),
m_nrRngRspsRecvd(0),
m_nrInvitedPollsRecvd(0),
m_rangingCW(0),
m_rangingBO(0),
m_nrRangingTransOpps(0),
m_isBackoffSet(false),
m_rangingAnomalies(0)
{
}
SSLinkManager::~SSLinkManager()
{
m_ss = nullptr;
}
void
SSLinkManager::DoDispose()
{
m_ss = nullptr;
}
void
SSLinkManager::SetBsEirp(uint16_t bs_eirp)
{
m_bsEirp = bs_eirp;
}
void
SSLinkManager::SetEirXPIrMax(uint16_t eir_x_p_ir_max)
{
m_eirXPIrMax = eir_x_p_ir_max;
}
void
SSLinkManager::SetRangingIntervalFound(bool rangingIntervalFound)
{
m_rangingIntervalFound = rangingIntervalFound;
}
bool
SSLinkManager::GetRangingIntervalFound() const
{
return m_rangingIntervalFound;
}
void
SSLinkManager::SetNrRangingTransOpps(uint8_t nrRangingTransOpps)
{
m_nrRangingTransOpps = nrRangingTransOpps;
}
void
SSLinkManager::SetRangingCW(uint8_t rangingCW)
{
m_rangingCW = rangingCW;
}
void
SSLinkManager::IncrementNrInvitedPollsRecvd()
{
m_nrInvitedPollsRecvd++;
}
EventId
SSLinkManager::GetDlMapSyncTimeoutEvent()
{
return m_dlMapSyncTimeoutEvent;
}
void
SSLinkManager::StartScanning(SubscriberStationNetDevice::EventType type, bool deleteParameters)
{
// temp parameter "type" just to check on expiry of which event the function was called
if (deleteParameters)
{
DeleteUplinkParameters();
}
NS_ASSERT_MSG(!m_ss->IsRegistered(),
"Subscriber Station: Error while scanning: Already registered with a BS");
if (m_ss->GetState() != SubscriberStationNetDevice::SS_STATE_IDLE)
{
m_dlChnlNr++;
}
// using max number of channel according to according to Section 8.5.1 of IEEE 802.16-2004
// standard.
if (m_dlChnlNr >= 200)
{
m_dlChnlNr = 0;
}
uint64_t dlChannel = m_ss->GetChannel(m_dlChnlNr);
m_ss->SetState(SubscriberStationNetDevice::SS_STATE_SCANNING);
m_ss->GetPhy()->StartScanning(dlChannel,
m_ss->GetIntervalT20(),
MakeCallback(&SSLinkManager::EndScanning, this));
}
void
SSLinkManager::EndScanning(bool status, uint64_t frequency)
{
if (status)
{
StartSynchronizing();
m_frequency = frequency;
}
else
{
StartScanning(SubscriberStationNetDevice::EVENT_NONE, false);
}
}
void
SSLinkManager::StartSynchronizing()
{
m_ss->SetState(SubscriberStationNetDevice::SS_STATE_SYNCHRONIZING);
m_ss->SetTimer(Simulator::Schedule(m_ss->GetIntervalT21(),
&SSLinkManager::StartScanning,
this,
SubscriberStationNetDevice::EVENT_DL_MAP_SYNC_TIMEOUT,
false),
m_dlMapSyncTimeoutEvent);
}
void
SSLinkManager::SendRangingRequest(uint8_t uiuc, uint16_t allocationSize)
{
NS_ASSERT_MSG(
m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_REG_RANG_INTRVL ||
m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_INV_RANG_INTRVL,
"SS: Error while sending a ranging request: the ss state should be "
"SS_STATE_WAITING_REG_RANG_INTRVL or SS_STATE_WAITING_INV_RANG_INTRVL");
if (m_nrRngReqsSent == 0) // sending the first time
{
m_pTxIrMax = CalculateMaxIRSignalStrength();
m_rngreq.SetReqDlBurstProfile(m_ss->GetBurstProfileManager()->GetBurstProfileToRequest());
m_rngreq.SetMacAddress(m_ss->GetMacAddress());
}
else
{
m_pTxIrMax++;
if (m_nrRngRspsRecvd > 0)
{
m_rngreq.SetRangingAnomalies(m_rangingAnomalies);
}
}
Ptr<Packet> packet = Create<Packet>();
Ptr<PacketBurst> burst = CreateObject<PacketBurst>();
packet->AddHeader(m_rngreq);
packet->AddHeader(ManagementMessageType(ManagementMessageType::MESSAGE_TYPE_RNG_REQ));
Ptr<WimaxConnection> connection;
if (m_rangingStatus == WimaxNetDevice::RANGING_STATUS_CONTINUE)
{
connection = m_ss->GetBasicConnection();
}
else // have been assigned BCID, means currently adjusting parameters
{
connection = m_ss->GetInitialRangingConnection();
}
m_ss->Enqueue(packet, MacHeaderType(), connection);
m_ss->SetState(SubscriberStationNetDevice::SS_STATE_WAITING_RNG_RSP);
m_ss->SetTimer(
Simulator::Schedule(m_ss->GetIntervalT3(), &SSLinkManager::StartContentionResolution, this),
m_waitForRngRspEvent);
m_nrRngReqsSent++;
NS_ASSERT_MSG(allocationSize ==
m_ss->GetCurrentUcd().GetChannelEncodings().GetRangReqOppSize() /
m_ss->GetPhy()->GetPsPerSymbol(),
"SS: Error while sending a ranging request: the allocation size is not correct");
// will work even if connection is not passed (i.e. null is passed) as scheduler will
// automatically select the same connection
m_ss->SendBurst(uiuc, allocationSize, connection);
}
void
SSLinkManager::StartContentionResolution()
{
NS_ASSERT_MSG(
m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_RNG_RSP ||
m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_REG_RANG_INTRVL ||
m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_ADJUSTING_PARAMETERS,
"SS: Can not start connection resolution: The SS state should be SS_STATE_WAITING_RNG_RSP "
"or SS_STATE_WAITING_REG_RANG_INTRVL or SS_STATE_ADJUSTING_PARAMETERS");
if (m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_WAITING_RNG_RSP)
{
m_ss->SetState(SubscriberStationNetDevice::SS_STATE_WAITING_REG_RANG_INTRVL);
IncreaseRangingRequestCW();
m_contentionRangingRetries++;
}
else if (m_ss->GetState() == SubscriberStationNetDevice::SS_STATE_ADJUSTING_PARAMETERS)
{
m_ss->SetState(SubscriberStationNetDevice::SS_STATE_WAITING_REG_RANG_INTRVL);
}
if (m_contentionRangingRetries == m_ss->GetMaxContentionRangingRetries())
{
StartScanning(SubscriberStationNetDevice::EVENT_NONE, false);
}
else
{
if (!m_isBackoffSet)
{
SelectRandomBackoff();
}
}
}
void
SSLinkManager::PerformBackoff()
{
Time deferTime;
Time timeToAllocation;
uint16_t nrPsPerRangOpp = m_ss->GetCurrentUcd().GetChannelEncodings().GetRangReqOppSize();
uint16_t oppSize = m_ss->GetCurrentUcd().GetChannelEncodings().GetRangReqOppSize() /
m_ss->GetPhy()->GetPsPerSymbol();
for (uint8_t deferTOs = 0; deferTOs < m_nrRangingTransOpps; deferTOs++)
{
if (m_rangingBO == 0)
{
deferTime =
Seconds(deferTOs * nrPsPerRangOpp * m_ss->GetPhy()->GetPsDuration().GetSeconds());
timeToAllocation = m_ss->GetTimeToAllocation(deferTime);
Simulator::Schedule(timeToAllocation,
&SSLinkManager::SendRangingRequest,
this,
OfdmUlBurstProfile::UIUC_INITIAL_RANGING,
oppSize);
m_rngReqFrameNumber = m_ss->GetNrFrames();
m_initRangOppNumber = deferTOs + 1;
m_isBackoffSet = false;
break;
}
m_rangingBO--;
}
}
void
SSLinkManager::SelectRandomBackoff()
{
NS_ASSERT_MSG(
m_rangingCW != 0 && m_rangingBO == 0,
"be sure that CW has been set and BO is not already set"); // ensuring CW has been set and
// BO is not already set
m_rangingBO = (rand() % m_rangingCW);
m_isBackoffSet = true;
}
void
SSLinkManager::IncreaseRangingRequestCW()
{
m_rangingCW =
std::min(uint8_t((m_rangingCW * 2 + 1) - 1), m_ss->GetCurrentUcd().GetRangingBackoffEnd());
}
void
SSLinkManager::ResetRangingRequestCW()
{
m_rangingCW =
(uint8_t)std::pow(2.0, (double)m_ss->GetCurrentUcd().GetRangingBackoffStart()) - 1;
}
void
SSLinkManager::PerformRanging(Cid cid, RngRsp rngrsp)
{
// need to distinguish initial ranging or periodic ranging
if (cid == m_ss->GetInitialRangingConnection()->GetCid())
{
if (rngrsp.GetFrameNumber() == m_rngReqFrameNumber &&
rngrsp.GetInitRangOppNumber() == m_initRangOppNumber)
{
Simulator::Cancel(m_waitForRngRspEvent);
m_nrRngRspsRecvd++;
// RNG-REQ was undecodable
ResetRangingRequestCW();
AdjustRangingParameters(rngrsp);
m_ss->SetState(SubscriberStationNetDevice::SS_STATE_ADJUSTING_PARAMETERS);
return;
}
if (m_ss->GetAddress() != rngrsp.GetMacAddress())
{
return;
}
m_ss->SetBasicConnection(CreateObject<WimaxConnection>(rngrsp.GetBasicCid(), Cid::BASIC));
m_ss->SetPrimaryConnection(
CreateObject<WimaxConnection>(rngrsp.GetPrimaryCid(), Cid::PRIMARY));
m_ss->SetAreManagementConnectionsAllocated(true);
}
else
{
// either periodic ranging or an additional RNG-RSP during initial ranging
}
m_nrRngRspsRecvd++;
if (m_waitForRngRspEvent.IsPending())
{
Simulator::Cancel(m_waitForRngRspEvent);
}
m_rangingStatus = (WimaxNetDevice::RangingStatus)rngrsp.GetRangStatus();
NS_ASSERT_MSG(m_rangingStatus == WimaxNetDevice::RANGING_STATUS_CONTINUE ||
m_rangingStatus == WimaxNetDevice::RANGING_STATUS_ABORT ||
m_rangingStatus == WimaxNetDevice::RANGING_STATUS_SUCCESS,
"SS: Can not perform ranging: the ranging status should be "
"RANGING_STATUS_CONTINUE or RANGING_STATUS_ABORT or RANGING_STATUS_SUCCESS");
if (m_rangingStatus == WimaxNetDevice::RANGING_STATUS_ABORT)
{
if (rngrsp.GetDlFreqOverride())
{
// code to move to new channel/frequency goes here
}
// deassigning basic and primary CIDs
m_ss->SetBasicConnection(nullptr);
m_ss->SetPrimaryConnection(nullptr);
m_ss->SetAreManagementConnectionsAllocated(false);
}
else
{
AdjustRangingParameters(rngrsp);
if (m_rangingStatus == WimaxNetDevice::RANGING_STATUS_SUCCESS)
{
m_ss->SetState(SubscriberStationNetDevice::SS_STATE_REGISTERED);
// initiate service flows
if (m_ss->HasServiceFlows() && !m_ss->GetAreServiceFlowsAllocated())
{
m_ss->GetServiceFlowManager()->InitiateServiceFlows();
}
NegotiateBasicCapabilities();
}
else
{
m_ss->SetState(SubscriberStationNetDevice::SS_STATE_WAITING_INV_RANG_INTRVL);
// wait for invited ranging interval assigned to its Basic CID
}
}
}
void
SSLinkManager::DeleteUplinkParameters()
{
m_ss->SetCurrentUcd(Ucd());
}
bool
SSLinkManager::IsUlChannelUsable()
{
// don't know how to check if usable, see Figure 58.
return true; // temporarily assuming usable
}
void
SSLinkManager::AdjustRangingParameters(const RngRsp& rngrsp)
{
#if 0 /* a template for future implementation following */
bool successful = true;
uint8_t temp = rngrsp.GetTimingAdjust ();
temp = rngrsp.GetPowerLevelAdjust ();
temp = rngrsp.GetOffsetFreqAdjust ();
// code for adjusting parameters goes here
if (!successful)
{
// code for setting ranging anomalies goes here
}
#endif
}
void
SSLinkManager::NegotiateBasicCapabilities()
{
// code to nagotiate basic capabilities goes here, ignored until very advanced stages
}
uint16_t
SSLinkManager::CalculateMaxIRSignalStrength()
{
// SS obtains RSSI measurement from the OFDM downlink preambles using a complex formula, page
// 486
uint16_t rss = 1;
if (m_bsEirp == 65535 || m_eirXPIrMax == 65535)
{
return GetMinTransmitPowerLevel();
}
else
{
return m_eirXPIrMax + m_bsEirp - rss;
}
return 0;
}
uint16_t
SSLinkManager::GetMinTransmitPowerLevel()
{
// code to calculate minimum transmit power level of the SS, see page 189 of amendment
return 10; // temp
}
void
SSLinkManager::ScheduleScanningRestart(Time interval,
SubscriberStationNetDevice::EventType eventType,
bool deleteUlParameters,
EventId& eventId)
{
m_ss->SetTimer(Simulator::Schedule(interval,
&SSLinkManager::StartScanning,
this,
eventType,
deleteUlParameters),
eventId);
}
} // namespace ns3