applications,core,internet,lte: Reduce indent by returning early
This commit is contained in:
committed by
Eduardo Almeida
parent
769ffe3ed0
commit
213fe52e5c
@@ -258,19 +258,16 @@ ThreeGppHttpClient::ConnectionSucceededCallback(Ptr<Socket> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << socket);
|
||||
|
||||
if (m_state == CONNECTING)
|
||||
{
|
||||
NS_ASSERT_MSG(m_socket == socket, "Invalid socket.");
|
||||
m_connectionEstablishedTrace(this);
|
||||
socket->SetRecvCallback(MakeCallback(&ThreeGppHttpClient::ReceivedDataCallback, this));
|
||||
NS_ASSERT(m_embeddedObjectsToBeRequested == 0);
|
||||
m_eventRequestMainObject =
|
||||
Simulator::ScheduleNow(&ThreeGppHttpClient::RequestMainObject, this);
|
||||
}
|
||||
else
|
||||
if (m_state != CONNECTING)
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for ConnectionSucceeded().");
|
||||
}
|
||||
|
||||
NS_ASSERT_MSG(m_socket == socket, "Invalid socket.");
|
||||
m_connectionEstablishedTrace(this);
|
||||
socket->SetRecvCallback(MakeCallback(&ThreeGppHttpClient::ReceivedDataCallback, this));
|
||||
NS_ASSERT(m_embeddedObjectsToBeRequested == 0);
|
||||
m_eventRequestMainObject = Simulator::ScheduleNow(&ThreeGppHttpClient::RequestMainObject, this);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -280,8 +277,7 @@ ThreeGppHttpClient::ConnectionFailedCallback(Ptr<Socket> socket)
|
||||
|
||||
if (m_state == CONNECTING)
|
||||
{
|
||||
NS_LOG_ERROR("Client failed to connect"
|
||||
<< " to remote address " << m_peer);
|
||||
NS_LOG_ERROR("Client failed to connect to remote address " << m_peer);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -378,72 +374,67 @@ ThreeGppHttpClient::OpenConnection()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
if (m_state == NOT_STARTED || m_state == EXPECTING_EMBEDDED_OBJECT ||
|
||||
m_state == PARSING_MAIN_OBJECT || m_state == READING)
|
||||
{
|
||||
m_socket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId());
|
||||
NS_ABORT_MSG_IF(m_peer.IsInvalid(), "Remote address not properly set");
|
||||
if (!m_local.IsInvalid())
|
||||
{
|
||||
NS_ABORT_MSG_IF((Inet6SocketAddress::IsMatchingType(m_peer) &&
|
||||
InetSocketAddress::IsMatchingType(m_local)) ||
|
||||
(InetSocketAddress::IsMatchingType(m_peer) &&
|
||||
Inet6SocketAddress::IsMatchingType(m_local)),
|
||||
"Incompatible peer and local address IP version");
|
||||
}
|
||||
if (InetSocketAddress::IsMatchingType(m_peer))
|
||||
{
|
||||
const auto ret [[maybe_unused]] =
|
||||
m_local.IsInvalid() ? m_socket->Bind() : m_socket->Bind(m_local);
|
||||
NS_LOG_DEBUG(this << " Bind() return value= " << ret
|
||||
<< " GetErrNo= " << m_socket->GetErrno() << ".");
|
||||
|
||||
const auto ipv4 = InetSocketAddress::ConvertFrom(m_peer).GetIpv4();
|
||||
const auto port = InetSocketAddress::ConvertFrom(m_peer).GetPort();
|
||||
NS_LOG_INFO(this << " Connecting to " << ipv4 << " port " << port << " / " << m_peer
|
||||
<< ".");
|
||||
m_socket->SetIpTos(m_tos);
|
||||
}
|
||||
else if (Inet6SocketAddress::IsMatchingType(m_peer))
|
||||
{
|
||||
const auto ret [[maybe_unused]] =
|
||||
m_local.IsInvalid() ? m_socket->Bind6() : m_socket->Bind(m_local);
|
||||
NS_LOG_DEBUG(this << " Bind6() return value= " << ret
|
||||
<< " GetErrNo= " << m_socket->GetErrno() << ".");
|
||||
|
||||
const auto ipv6 = Inet6SocketAddress::ConvertFrom(m_peer).GetIpv6();
|
||||
const auto port = Inet6SocketAddress::ConvertFrom(m_peer).GetPort();
|
||||
NS_LOG_INFO(this << " Connecting to " << ipv6 << " port " << port << " / " << m_peer
|
||||
<< ".");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERT_MSG(false, "Incompatible address type: " << m_peer);
|
||||
}
|
||||
|
||||
const auto ret [[maybe_unused]] = m_socket->Connect(m_peer);
|
||||
NS_LOG_DEBUG(this << " Connect() return value= " << ret
|
||||
<< " GetErrNo= " << m_socket->GetErrno() << ".");
|
||||
|
||||
NS_ASSERT_MSG(m_socket, "Failed creating socket.");
|
||||
|
||||
SwitchToState(CONNECTING);
|
||||
|
||||
m_socket->SetConnectCallback(
|
||||
MakeCallback(&ThreeGppHttpClient::ConnectionSucceededCallback, this),
|
||||
MakeCallback(&ThreeGppHttpClient::ConnectionFailedCallback, this));
|
||||
m_socket->SetCloseCallbacks(MakeCallback(&ThreeGppHttpClient::NormalCloseCallback, this),
|
||||
MakeCallback(&ThreeGppHttpClient::ErrorCloseCallback, this));
|
||||
m_socket->SetRecvCallback(MakeCallback(&ThreeGppHttpClient::ReceivedDataCallback, this));
|
||||
m_socket->SetAttribute("MaxSegLifetime", DoubleValue(0.02)); // 20 ms.
|
||||
|
||||
} // end of `if (m_state == {NOT_STARTED, EXPECTING_EMBEDDED_OBJECT, PARSING_MAIN_OBJECT,
|
||||
// READING})`
|
||||
else
|
||||
if (m_state != NOT_STARTED && m_state != EXPECTING_EMBEDDED_OBJECT &&
|
||||
m_state != PARSING_MAIN_OBJECT && m_state != READING)
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for OpenConnection().");
|
||||
}
|
||||
|
||||
m_socket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId());
|
||||
NS_ABORT_MSG_IF(m_peer.IsInvalid(), "Remote address not properly set");
|
||||
if (!m_local.IsInvalid())
|
||||
{
|
||||
NS_ABORT_MSG_IF((Inet6SocketAddress::IsMatchingType(m_peer) &&
|
||||
InetSocketAddress::IsMatchingType(m_local)) ||
|
||||
(InetSocketAddress::IsMatchingType(m_peer) &&
|
||||
Inet6SocketAddress::IsMatchingType(m_local)),
|
||||
"Incompatible peer and local address IP version");
|
||||
}
|
||||
if (InetSocketAddress::IsMatchingType(m_peer))
|
||||
{
|
||||
const auto ret [[maybe_unused]] =
|
||||
m_local.IsInvalid() ? m_socket->Bind() : m_socket->Bind(m_local);
|
||||
NS_LOG_DEBUG(this << " Bind() return value= " << ret
|
||||
<< " GetErrNo= " << m_socket->GetErrno() << ".");
|
||||
|
||||
const auto ipv4 = InetSocketAddress::ConvertFrom(m_peer).GetIpv4();
|
||||
const auto port = InetSocketAddress::ConvertFrom(m_peer).GetPort();
|
||||
NS_LOG_INFO(this << " Connecting to " << ipv4 << " port " << port << " / " << m_peer
|
||||
<< ".");
|
||||
m_socket->SetIpTos(m_tos);
|
||||
}
|
||||
else if (Inet6SocketAddress::IsMatchingType(m_peer))
|
||||
{
|
||||
const auto ret [[maybe_unused]] =
|
||||
m_local.IsInvalid() ? m_socket->Bind6() : m_socket->Bind(m_local);
|
||||
NS_LOG_DEBUG(this << " Bind6() return value= " << ret
|
||||
<< " GetErrNo= " << m_socket->GetErrno() << ".");
|
||||
|
||||
const auto ipv6 = Inet6SocketAddress::ConvertFrom(m_peer).GetIpv6();
|
||||
const auto port = Inet6SocketAddress::ConvertFrom(m_peer).GetPort();
|
||||
NS_LOG_INFO(this << " Connecting to " << ipv6 << " port " << port << " / " << m_peer
|
||||
<< ".");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERT_MSG(false, "Incompatible address type: " << m_peer);
|
||||
}
|
||||
|
||||
const auto ret [[maybe_unused]] = m_socket->Connect(m_peer);
|
||||
NS_LOG_DEBUG(this << " Connect() return value= " << ret << " GetErrNo= " << m_socket->GetErrno()
|
||||
<< ".");
|
||||
|
||||
NS_ASSERT_MSG(m_socket, "Failed creating socket.");
|
||||
|
||||
SwitchToState(CONNECTING);
|
||||
|
||||
m_socket->SetConnectCallback(
|
||||
MakeCallback(&ThreeGppHttpClient::ConnectionSucceededCallback, this),
|
||||
MakeCallback(&ThreeGppHttpClient::ConnectionFailedCallback, this));
|
||||
m_socket->SetCloseCallbacks(MakeCallback(&ThreeGppHttpClient::NormalCloseCallback, this),
|
||||
MakeCallback(&ThreeGppHttpClient::ErrorCloseCallback, this));
|
||||
m_socket->SetRecvCallback(MakeCallback(&ThreeGppHttpClient::ReceivedDataCallback, this));
|
||||
m_socket->SetAttribute("MaxSegLifetime", DoubleValue(0.02)); // 20 ms.
|
||||
} // end of `void OpenConnection ()`
|
||||
|
||||
void
|
||||
@@ -451,37 +442,35 @@ ThreeGppHttpClient::RequestMainObject()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
if (m_state == CONNECTING || m_state == READING)
|
||||
if (m_state != CONNECTING && m_state != READING)
|
||||
{
|
||||
ThreeGppHttpHeader header;
|
||||
header.SetContentLength(0); // Request does not need any content length.
|
||||
header.SetContentType(ThreeGppHttpHeader::MAIN_OBJECT);
|
||||
header.SetClientTs(Simulator::Now());
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for RequestMainObject().");
|
||||
}
|
||||
|
||||
const auto requestSize = m_httpVariables->GetRequestSize();
|
||||
auto packet = Create<Packet>(requestSize);
|
||||
packet->AddHeader(header);
|
||||
const auto packetSize = packet->GetSize();
|
||||
m_txMainObjectRequestTrace(packet);
|
||||
m_txTrace(packet);
|
||||
const auto actualBytes = m_socket->Send(packet);
|
||||
NS_LOG_DEBUG(this << " Send() packet " << packet << " of " << packet->GetSize() << " bytes,"
|
||||
<< " return value= " << actualBytes << ".");
|
||||
if (actualBytes != static_cast<int>(packetSize))
|
||||
{
|
||||
NS_LOG_ERROR(this << " Failed to send request for embedded object,"
|
||||
<< " GetErrNo= " << m_socket->GetErrno() << ","
|
||||
<< " waiting for another Tx opportunity.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SwitchToState(EXPECTING_MAIN_OBJECT);
|
||||
m_pageLoadStartTs = Simulator::Now(); // start counting page loading time
|
||||
}
|
||||
ThreeGppHttpHeader header;
|
||||
header.SetContentLength(0); // Request does not need any content length.
|
||||
header.SetContentType(ThreeGppHttpHeader::MAIN_OBJECT);
|
||||
header.SetClientTs(Simulator::Now());
|
||||
|
||||
const auto requestSize = m_httpVariables->GetRequestSize();
|
||||
auto packet = Create<Packet>(requestSize);
|
||||
packet->AddHeader(header);
|
||||
const auto packetSize = packet->GetSize();
|
||||
m_txMainObjectRequestTrace(packet);
|
||||
m_txTrace(packet);
|
||||
const auto actualBytes = m_socket->Send(packet);
|
||||
NS_LOG_DEBUG(this << " Send() packet " << packet << " of " << packet->GetSize() << " bytes,"
|
||||
<< " return value= " << actualBytes << ".");
|
||||
if (actualBytes != static_cast<int>(packetSize))
|
||||
{
|
||||
NS_LOG_ERROR(this << " Failed to send request for embedded object,"
|
||||
<< " GetErrNo= " << m_socket->GetErrno() << ","
|
||||
<< " waiting for another Tx opportunity.");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for RequestMainObject().");
|
||||
SwitchToState(EXPECTING_MAIN_OBJECT);
|
||||
m_pageLoadStartTs = Simulator::Now(); // start counting page loading time
|
||||
}
|
||||
|
||||
} // end of `void RequestMainObject ()`
|
||||
@@ -491,47 +480,43 @@ ThreeGppHttpClient::RequestEmbeddedObject()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
if (m_state == CONNECTING || m_state == PARSING_MAIN_OBJECT ||
|
||||
m_state == EXPECTING_EMBEDDED_OBJECT)
|
||||
if (m_state != CONNECTING && m_state != PARSING_MAIN_OBJECT &&
|
||||
m_state != EXPECTING_EMBEDDED_OBJECT)
|
||||
{
|
||||
if (m_embeddedObjectsToBeRequested > 0)
|
||||
{
|
||||
ThreeGppHttpHeader header;
|
||||
header.SetContentLength(0); // Request does not need any content length.
|
||||
header.SetContentType(ThreeGppHttpHeader::EMBEDDED_OBJECT);
|
||||
header.SetClientTs(Simulator::Now());
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for RequestEmbeddedObject().");
|
||||
}
|
||||
|
||||
const auto requestSize = m_httpVariables->GetRequestSize();
|
||||
auto packet = Create<Packet>(requestSize);
|
||||
packet->AddHeader(header);
|
||||
const auto packetSize = packet->GetSize();
|
||||
m_txEmbeddedObjectRequestTrace(packet);
|
||||
m_txTrace(packet);
|
||||
const auto actualBytes = m_socket->Send(packet);
|
||||
NS_LOG_DEBUG(this << " Send() packet " << packet << " of " << packet->GetSize()
|
||||
<< " bytes,"
|
||||
<< " return value= " << actualBytes << ".");
|
||||
if (m_embeddedObjectsToBeRequested == 0)
|
||||
{
|
||||
NS_LOG_WARN(this << " No embedded object to be requested.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (actualBytes != static_cast<int>(packetSize))
|
||||
{
|
||||
NS_LOG_ERROR(this << " Failed to send request for embedded object,"
|
||||
<< " GetErrNo= " << m_socket->GetErrno() << ","
|
||||
<< " waiting for another Tx opportunity.");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_embeddedObjectsToBeRequested--;
|
||||
SwitchToState(EXPECTING_EMBEDDED_OBJECT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN(this << " No embedded object to be requested.");
|
||||
}
|
||||
ThreeGppHttpHeader header;
|
||||
header.SetContentLength(0); // Request does not need any content length.
|
||||
header.SetContentType(ThreeGppHttpHeader::EMBEDDED_OBJECT);
|
||||
header.SetClientTs(Simulator::Now());
|
||||
|
||||
const auto requestSize = m_httpVariables->GetRequestSize();
|
||||
auto packet = Create<Packet>(requestSize);
|
||||
packet->AddHeader(header);
|
||||
const auto packetSize = packet->GetSize();
|
||||
m_txEmbeddedObjectRequestTrace(packet);
|
||||
m_txTrace(packet);
|
||||
const auto actualBytes = m_socket->Send(packet);
|
||||
NS_LOG_DEBUG(this << " Send() packet " << packet << " of " << packet->GetSize() << " bytes,"
|
||||
<< " return value= " << actualBytes << ".");
|
||||
|
||||
if (actualBytes != static_cast<int>(packetSize))
|
||||
{
|
||||
NS_LOG_ERROR(this << " Failed to send request for embedded object,"
|
||||
<< " GetErrNo= " << m_socket->GetErrno() << ","
|
||||
<< " waiting for another Tx opportunity.");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for RequestEmbeddedObject().");
|
||||
m_embeddedObjectsToBeRequested--;
|
||||
SwitchToState(EXPECTING_EMBEDDED_OBJECT);
|
||||
}
|
||||
|
||||
} // end of `void RequestEmbeddedObject ()`
|
||||
@@ -541,59 +526,53 @@ ThreeGppHttpClient::ReceiveMainObject(Ptr<Packet> packet, const Address& from)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << packet << from);
|
||||
|
||||
if (m_state == EXPECTING_MAIN_OBJECT)
|
||||
{
|
||||
/*
|
||||
* In the following call to Receive(), #m_objectBytesToBeReceived *will*
|
||||
* be updated. #m_objectClientTs and #m_objectServerTs *may* be updated.
|
||||
* ThreeGppHttpHeader will be removed from the packet, if it is the first
|
||||
* packet of the object to be received; the header will be available in
|
||||
* #m_constructedPacketHeader.
|
||||
* #m_constructedPacket will also be updated.
|
||||
*/
|
||||
Receive(packet);
|
||||
m_rxMainObjectPacketTrace(packet);
|
||||
|
||||
if (m_objectBytesToBeReceived > 0)
|
||||
{
|
||||
/*
|
||||
* There are more packets of this main object, so just stay still
|
||||
* and wait until they arrive.
|
||||
*/
|
||||
NS_LOG_INFO(this << " " << m_objectBytesToBeReceived << " byte(s)"
|
||||
<< " remains from this chunk of main object.");
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* This is the last packet of this main object. Acknowledge the
|
||||
* reception of a whole main object
|
||||
*/
|
||||
NS_LOG_INFO(this << " Finished receiving a main object.");
|
||||
m_rxMainObjectTrace(this, m_constructedPacket);
|
||||
|
||||
if (!m_objectServerTs.IsZero())
|
||||
{
|
||||
m_rxDelayTrace(Simulator::Now() - m_objectServerTs, from);
|
||||
m_objectServerTs = MilliSeconds(0); // Reset back to zero.
|
||||
}
|
||||
|
||||
if (!m_objectClientTs.IsZero())
|
||||
{
|
||||
m_rxRttTrace(Simulator::Now() - m_objectClientTs, from);
|
||||
m_objectClientTs = MilliSeconds(0); // Reset back to zero.
|
||||
}
|
||||
|
||||
EnterParsingTime();
|
||||
|
||||
} // end of else of `if (m_objectBytesToBeReceived > 0)`
|
||||
|
||||
} // end of `if (m_state == EXPECTING_MAIN_OBJECT)`
|
||||
else
|
||||
if (m_state != EXPECTING_MAIN_OBJECT)
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for ReceiveMainObject().");
|
||||
}
|
||||
|
||||
/*
|
||||
* In the following call to Receive(), #m_objectBytesToBeReceived *will*
|
||||
* be updated. #m_objectClientTs and #m_objectServerTs *may* be updated.
|
||||
* ThreeGppHttpHeader will be removed from the packet, if it is the first
|
||||
* packet of the object to be received; the header will be available in
|
||||
* #m_constructedPacketHeader.
|
||||
* #m_constructedPacket will also be updated.
|
||||
*/
|
||||
Receive(packet);
|
||||
m_rxMainObjectPacketTrace(packet);
|
||||
|
||||
if (m_objectBytesToBeReceived > 0)
|
||||
{
|
||||
/*
|
||||
* There are more packets of this main object, so just stay still
|
||||
* and wait until they arrive.
|
||||
*/
|
||||
NS_LOG_INFO(this << " " << m_objectBytesToBeReceived << " byte(s)"
|
||||
<< " remains from this chunk of main object.");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the last packet of this main object. Acknowledge the
|
||||
* reception of a whole main object
|
||||
*/
|
||||
NS_LOG_INFO(this << " Finished receiving a main object.");
|
||||
m_rxMainObjectTrace(this, m_constructedPacket);
|
||||
|
||||
if (!m_objectServerTs.IsZero())
|
||||
{
|
||||
m_rxDelayTrace(Simulator::Now() - m_objectServerTs, from);
|
||||
m_objectServerTs = MilliSeconds(0); // Reset back to zero.
|
||||
}
|
||||
|
||||
if (!m_objectClientTs.IsZero())
|
||||
{
|
||||
m_rxRttTrace(Simulator::Now() - m_objectClientTs, from);
|
||||
m_objectClientTs = MilliSeconds(0); // Reset back to zero.
|
||||
}
|
||||
|
||||
EnterParsingTime();
|
||||
} // end of `void ReceiveMainObject (Ptr<Packet> packet)`
|
||||
|
||||
void
|
||||
@@ -601,75 +580,69 @@ ThreeGppHttpClient::ReceiveEmbeddedObject(Ptr<Packet> packet, const Address& fro
|
||||
{
|
||||
NS_LOG_FUNCTION(this << packet << from);
|
||||
|
||||
if (m_state == EXPECTING_EMBEDDED_OBJECT)
|
||||
{
|
||||
/*
|
||||
* In the following call to Receive(), #m_objectBytesToBeReceived *will*
|
||||
* be updated. #m_objectClientTs and #m_objectServerTs *may* be updated.
|
||||
* ThreeGppHttpHeader will be removed from the packet, if it is the first
|
||||
* packet of the object to be received; the header will be available in
|
||||
* #m_constructedPacket, which will also be updated.
|
||||
*/
|
||||
Receive(packet);
|
||||
m_rxEmbeddedObjectPacketTrace(packet);
|
||||
|
||||
if (m_objectBytesToBeReceived > 0)
|
||||
{
|
||||
/*
|
||||
* There are more packets of this embedded object, so just stay
|
||||
* still and wait until they arrive.
|
||||
*/
|
||||
NS_LOG_INFO(this << " " << m_objectBytesToBeReceived << " byte(s)"
|
||||
<< " remains from this chunk of embedded object");
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* This is the last packet of this embedded object. Acknowledge
|
||||
* the reception of a whole embedded object
|
||||
*/
|
||||
NS_LOG_INFO(this << " Finished receiving an embedded object.");
|
||||
m_rxEmbeddedObjectTrace(this, m_constructedPacket);
|
||||
|
||||
if (!m_objectServerTs.IsZero())
|
||||
{
|
||||
m_rxDelayTrace(Simulator::Now() - m_objectServerTs, from);
|
||||
m_objectServerTs = MilliSeconds(0); // Reset back to zero.
|
||||
}
|
||||
|
||||
if (!m_objectClientTs.IsZero())
|
||||
{
|
||||
m_rxRttTrace(Simulator::Now() - m_objectClientTs, from);
|
||||
m_objectClientTs = MilliSeconds(0); // Reset back to zero.
|
||||
}
|
||||
|
||||
if (m_embeddedObjectsToBeRequested > 0)
|
||||
{
|
||||
NS_LOG_INFO(this << " " << m_embeddedObjectsToBeRequested
|
||||
<< " more embedded object(s) to be requested.");
|
||||
// Immediately request another using the existing connection.
|
||||
m_eventRequestEmbeddedObject =
|
||||
Simulator::ScheduleNow(&ThreeGppHttpClient::RequestEmbeddedObject, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* There is no more embedded object, the web page has been
|
||||
* downloaded completely. Now is the time to read it.
|
||||
*/
|
||||
NS_LOG_INFO(this << " Finished receiving a web page.");
|
||||
FinishReceivingPage(); // trigger callback for page loading time
|
||||
EnterReadingTime();
|
||||
}
|
||||
|
||||
} // end of else of `if (m_objectBytesToBeReceived > 0)`
|
||||
|
||||
} // end of `if (m_state == EXPECTING_EMBEDDED_OBJECT)`
|
||||
else
|
||||
if (m_state != EXPECTING_EMBEDDED_OBJECT)
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for ReceiveEmbeddedObject().");
|
||||
}
|
||||
|
||||
/*
|
||||
* In the following call to Receive(), #m_objectBytesToBeReceived *will*
|
||||
* be updated. #m_objectClientTs and #m_objectServerTs *may* be updated.
|
||||
* ThreeGppHttpHeader will be removed from the packet, if it is the first
|
||||
* packet of the object to be received; the header will be available in
|
||||
* #m_constructedPacket, which will also be updated.
|
||||
*/
|
||||
Receive(packet);
|
||||
m_rxEmbeddedObjectPacketTrace(packet);
|
||||
|
||||
if (m_objectBytesToBeReceived > 0)
|
||||
{
|
||||
/*
|
||||
* There are more packets of this embedded object, so just stay
|
||||
* still and wait until they arrive.
|
||||
*/
|
||||
NS_LOG_INFO(this << " " << m_objectBytesToBeReceived << " byte(s)"
|
||||
<< " remains from this chunk of embedded object");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the last packet of this embedded object. Acknowledge
|
||||
* the reception of a whole embedded object
|
||||
*/
|
||||
NS_LOG_INFO(this << " Finished receiving an embedded object.");
|
||||
m_rxEmbeddedObjectTrace(this, m_constructedPacket);
|
||||
|
||||
if (!m_objectServerTs.IsZero())
|
||||
{
|
||||
m_rxDelayTrace(Simulator::Now() - m_objectServerTs, from);
|
||||
m_objectServerTs = MilliSeconds(0); // Reset back to zero.
|
||||
}
|
||||
|
||||
if (!m_objectClientTs.IsZero())
|
||||
{
|
||||
m_rxRttTrace(Simulator::Now() - m_objectClientTs, from);
|
||||
m_objectClientTs = MilliSeconds(0); // Reset back to zero.
|
||||
}
|
||||
|
||||
if (m_embeddedObjectsToBeRequested > 0)
|
||||
{
|
||||
NS_LOG_INFO(this << " " << m_embeddedObjectsToBeRequested
|
||||
<< " more embedded object(s) to be requested.");
|
||||
// Immediately request another using the existing connection.
|
||||
m_eventRequestEmbeddedObject =
|
||||
Simulator::ScheduleNow(&ThreeGppHttpClient::RequestEmbeddedObject, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* There is no more embedded object, the web page has been
|
||||
* downloaded completely. Now is the time to read it.
|
||||
*/
|
||||
NS_LOG_INFO(this << " Finished receiving a web page.");
|
||||
FinishReceivingPage(); // trigger callback for page loading time
|
||||
EnterReadingTime();
|
||||
}
|
||||
} // end of `void ReceiveEmbeddedObject (Ptr<Packet> packet)`
|
||||
|
||||
void
|
||||
@@ -733,19 +706,17 @@ ThreeGppHttpClient::EnterParsingTime()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
if (m_state == EXPECTING_MAIN_OBJECT)
|
||||
{
|
||||
const auto parsingTime = m_httpVariables->GetParsingTime();
|
||||
NS_LOG_INFO(this << " The parsing of this main object"
|
||||
<< " will complete in " << parsingTime.As(Time::S) << ".");
|
||||
m_eventParseMainObject =
|
||||
Simulator::Schedule(parsingTime, &ThreeGppHttpClient::ParseMainObject, this);
|
||||
SwitchToState(PARSING_MAIN_OBJECT);
|
||||
}
|
||||
else
|
||||
if (m_state != EXPECTING_MAIN_OBJECT)
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for EnterParsingTime().");
|
||||
}
|
||||
|
||||
const auto parsingTime = m_httpVariables->GetParsingTime();
|
||||
NS_LOG_INFO(this << " The parsing of this main object will complete in "
|
||||
<< parsingTime.As(Time::S) << ".");
|
||||
m_eventParseMainObject =
|
||||
Simulator::Schedule(parsingTime, &ThreeGppHttpClient::ParseMainObject, this);
|
||||
SwitchToState(PARSING_MAIN_OBJECT);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -753,37 +724,35 @@ ThreeGppHttpClient::ParseMainObject()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
if (m_state == PARSING_MAIN_OBJECT)
|
||||
if (m_state != PARSING_MAIN_OBJECT)
|
||||
{
|
||||
m_embeddedObjectsToBeRequested = m_httpVariables->GetNumOfEmbeddedObjects();
|
||||
// saving total number of embedded objects
|
||||
m_numberEmbeddedObjectsRequested = m_embeddedObjectsToBeRequested;
|
||||
NS_LOG_INFO(this << " Parsing has determined " << m_embeddedObjectsToBeRequested
|
||||
<< " embedded object(s) in the main object.");
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for ParseMainObject().");
|
||||
}
|
||||
|
||||
if (m_embeddedObjectsToBeRequested > 0)
|
||||
{
|
||||
/*
|
||||
* Immediately request the first embedded object using the
|
||||
* existing connection.
|
||||
*/
|
||||
m_eventRequestEmbeddedObject =
|
||||
Simulator::ScheduleNow(&ThreeGppHttpClient::RequestEmbeddedObject, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* There is no embedded object in the main object. So sit back and
|
||||
* enjoy the plain web page.
|
||||
*/
|
||||
NS_LOG_INFO(this << " Finished receiving a web page.");
|
||||
FinishReceivingPage(); // trigger callback for page loading time
|
||||
EnterReadingTime();
|
||||
}
|
||||
m_embeddedObjectsToBeRequested = m_httpVariables->GetNumOfEmbeddedObjects();
|
||||
// saving total number of embedded objects
|
||||
m_numberEmbeddedObjectsRequested = m_embeddedObjectsToBeRequested;
|
||||
NS_LOG_INFO(this << " Parsing has determined " << m_embeddedObjectsToBeRequested
|
||||
<< " embedded object(s) in the main object.");
|
||||
|
||||
if (m_embeddedObjectsToBeRequested > 0)
|
||||
{
|
||||
/*
|
||||
* Immediately request the first embedded object using the
|
||||
* existing connection.
|
||||
*/
|
||||
m_eventRequestEmbeddedObject =
|
||||
Simulator::ScheduleNow(&ThreeGppHttpClient::RequestEmbeddedObject, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for ParseMainObject().");
|
||||
/*
|
||||
* There is no embedded object in the main object. So sit back and
|
||||
* enjoy the plain web page.
|
||||
*/
|
||||
NS_LOG_INFO(this << " Finished receiving a web page.");
|
||||
FinishReceivingPage(); // trigger callback for page loading time
|
||||
EnterReadingTime();
|
||||
}
|
||||
|
||||
} // end of `void ParseMainObject ()`
|
||||
@@ -793,21 +762,19 @@ ThreeGppHttpClient::EnterReadingTime()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
if (m_state == EXPECTING_EMBEDDED_OBJECT || m_state == PARSING_MAIN_OBJECT)
|
||||
{
|
||||
const auto readingTime = m_httpVariables->GetReadingTime();
|
||||
NS_LOG_INFO(this << " Client will finish reading this web page in "
|
||||
<< readingTime.As(Time::S) << ".");
|
||||
|
||||
// Schedule a request of another main object once the reading time expires.
|
||||
m_eventRequestMainObject =
|
||||
Simulator::Schedule(readingTime, &ThreeGppHttpClient::RequestMainObject, this);
|
||||
SwitchToState(READING);
|
||||
}
|
||||
else
|
||||
if (m_state != EXPECTING_EMBEDDED_OBJECT && m_state != PARSING_MAIN_OBJECT)
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for EnterReadingTime().");
|
||||
}
|
||||
|
||||
const auto readingTime = m_httpVariables->GetReadingTime();
|
||||
NS_LOG_INFO(this << " Client will finish reading this web page in " << readingTime.As(Time::S)
|
||||
<< ".");
|
||||
|
||||
// Schedule a request of another main object once the reading time expires.
|
||||
m_eventRequestMainObject =
|
||||
Simulator::Schedule(readingTime, &ThreeGppHttpClient::RequestMainObject, this);
|
||||
SwitchToState(READING);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -221,76 +221,70 @@ ThreeGppHttpServer::StartApplication()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
if (m_state == NOT_STARTED)
|
||||
{
|
||||
m_httpVariables->Initialize();
|
||||
if (!m_initialSocket)
|
||||
{
|
||||
// Find the current default MTU value of TCP sockets.
|
||||
Ptr<const ns3::AttributeValue> previousSocketMtu;
|
||||
const TypeId tcpSocketTid = TcpSocket::GetTypeId();
|
||||
for (uint32_t i = 0; i < tcpSocketTid.GetAttributeN(); i++)
|
||||
{
|
||||
TypeId::AttributeInformation attrInfo = tcpSocketTid.GetAttribute(i);
|
||||
if (attrInfo.name == "SegmentSize")
|
||||
{
|
||||
previousSocketMtu = attrInfo.initialValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Creating a TCP socket to connect to the server.
|
||||
m_initialSocket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId());
|
||||
m_initialSocket->SetAttribute("SegmentSize", UintegerValue(m_mtuSize));
|
||||
|
||||
NS_ABORT_MSG_IF(m_local.IsInvalid(), "Local address not properly set");
|
||||
if (InetSocketAddress::IsMatchingType(m_local))
|
||||
{
|
||||
const auto ipv4 [[maybe_unused]] =
|
||||
InetSocketAddress::ConvertFrom(m_local).GetIpv4();
|
||||
m_initialSocket->SetIpTos(m_tos); // Affects only IPv4 sockets.
|
||||
NS_LOG_INFO(this << " Binding on " << ipv4 << " port " << m_port << " / " << m_local
|
||||
<< ".");
|
||||
}
|
||||
else if (Inet6SocketAddress::IsMatchingType(m_local))
|
||||
{
|
||||
const auto ipv6 [[maybe_unused]] =
|
||||
Inet6SocketAddress::ConvertFrom(m_local).GetIpv6();
|
||||
NS_LOG_INFO(this << " Binding on " << ipv6 << " port " << m_port << " / " << m_local
|
||||
<< ".");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG("Incompatible local address");
|
||||
}
|
||||
|
||||
auto ret [[maybe_unused]] = m_initialSocket->Bind(m_local);
|
||||
NS_LOG_DEBUG(this << " Bind() return value= " << ret
|
||||
<< " GetErrNo= " << m_initialSocket->GetErrno() << ".");
|
||||
|
||||
ret = m_initialSocket->Listen();
|
||||
NS_LOG_DEBUG(this << " Listen () return value= " << ret
|
||||
<< " GetErrNo= " << m_initialSocket->GetErrno() << ".");
|
||||
|
||||
NS_ASSERT_MSG(m_initialSocket, "Failed creating socket.");
|
||||
m_initialSocket->SetAcceptCallback(
|
||||
MakeCallback(&ThreeGppHttpServer::ConnectionRequestCallback, this),
|
||||
MakeCallback(&ThreeGppHttpServer::NewConnectionCreatedCallback, this));
|
||||
m_initialSocket->SetCloseCallbacks(
|
||||
MakeCallback(&ThreeGppHttpServer::NormalCloseCallback, this),
|
||||
MakeCallback(&ThreeGppHttpServer::ErrorCloseCallback, this));
|
||||
m_initialSocket->SetRecvCallback(
|
||||
MakeCallback(&ThreeGppHttpServer::ReceivedDataCallback, this));
|
||||
m_initialSocket->SetSendCallback(MakeCallback(&ThreeGppHttpServer::SendCallback, this));
|
||||
} // end of `if (m_initialSocket == 0)`
|
||||
|
||||
SwitchToState(STARTED);
|
||||
|
||||
} // end of `if (m_state == NOT_STARTED)`
|
||||
else
|
||||
if (m_state != NOT_STARTED)
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid state " << GetStateString() << " for StartApplication().");
|
||||
}
|
||||
|
||||
m_httpVariables->Initialize();
|
||||
if (!m_initialSocket)
|
||||
{
|
||||
// Find the current default MTU value of TCP sockets.
|
||||
Ptr<const ns3::AttributeValue> previousSocketMtu;
|
||||
const TypeId tcpSocketTid = TcpSocket::GetTypeId();
|
||||
for (uint32_t i = 0; i < tcpSocketTid.GetAttributeN(); i++)
|
||||
{
|
||||
TypeId::AttributeInformation attrInfo = tcpSocketTid.GetAttribute(i);
|
||||
if (attrInfo.name == "SegmentSize")
|
||||
{
|
||||
previousSocketMtu = attrInfo.initialValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Creating a TCP socket to connect to the server.
|
||||
m_initialSocket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId());
|
||||
m_initialSocket->SetAttribute("SegmentSize", UintegerValue(m_mtuSize));
|
||||
|
||||
NS_ABORT_MSG_IF(m_local.IsInvalid(), "Local address not properly set");
|
||||
if (InetSocketAddress::IsMatchingType(m_local))
|
||||
{
|
||||
const auto ipv4 [[maybe_unused]] = InetSocketAddress::ConvertFrom(m_local).GetIpv4();
|
||||
m_initialSocket->SetIpTos(m_tos); // Affects only IPv4 sockets.
|
||||
NS_LOG_INFO(this << " Binding on " << ipv4 << " port " << m_port << " / " << m_local
|
||||
<< ".");
|
||||
}
|
||||
else if (Inet6SocketAddress::IsMatchingType(m_local))
|
||||
{
|
||||
const auto ipv6 [[maybe_unused]] = Inet6SocketAddress::ConvertFrom(m_local).GetIpv6();
|
||||
NS_LOG_INFO(this << " Binding on " << ipv6 << " port " << m_port << " / " << m_local
|
||||
<< ".");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG("Incompatible local address");
|
||||
}
|
||||
|
||||
auto ret [[maybe_unused]] = m_initialSocket->Bind(m_local);
|
||||
NS_LOG_DEBUG(this << " Bind() return value= " << ret
|
||||
<< " GetErrNo= " << m_initialSocket->GetErrno() << ".");
|
||||
|
||||
ret = m_initialSocket->Listen();
|
||||
NS_LOG_DEBUG(this << " Listen () return value= " << ret
|
||||
<< " GetErrNo= " << m_initialSocket->GetErrno() << ".");
|
||||
|
||||
NS_ASSERT_MSG(m_initialSocket, "Failed creating socket.");
|
||||
m_initialSocket->SetAcceptCallback(
|
||||
MakeCallback(&ThreeGppHttpServer::ConnectionRequestCallback, this),
|
||||
MakeCallback(&ThreeGppHttpServer::NewConnectionCreatedCallback, this));
|
||||
m_initialSocket->SetCloseCallbacks(
|
||||
MakeCallback(&ThreeGppHttpServer::NormalCloseCallback, this),
|
||||
MakeCallback(&ThreeGppHttpServer::ErrorCloseCallback, this));
|
||||
m_initialSocket->SetRecvCallback(
|
||||
MakeCallback(&ThreeGppHttpServer::ReceivedDataCallback, this));
|
||||
m_initialSocket->SetSendCallback(MakeCallback(&ThreeGppHttpServer::SendCallback, this));
|
||||
} // end of `if (m_initialSocket == 0)`
|
||||
|
||||
SwitchToState(STARTED);
|
||||
} // end of `void StartApplication ()`
|
||||
|
||||
void
|
||||
@@ -485,49 +479,50 @@ ThreeGppHttpServer::SendCallback(Ptr<Socket> socket, uint32_t availableBufferSiz
|
||||
{
|
||||
NS_LOG_FUNCTION(this << socket << availableBufferSize);
|
||||
|
||||
if (!m_txBuffer->IsBufferEmpty(socket))
|
||||
if (m_txBuffer->IsBufferEmpty(socket))
|
||||
{
|
||||
const auto txBufferSize [[maybe_unused]] = m_txBuffer->GetBufferSize(socket);
|
||||
const auto actualSent [[maybe_unused]] = ServeFromTxBuffer(socket);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto txBufferSize [[maybe_unused]] = m_txBuffer->GetBufferSize(socket);
|
||||
const auto actualSent [[maybe_unused]] = ServeFromTxBuffer(socket);
|
||||
|
||||
#ifdef NS3_LOG_ENABLE
|
||||
// Some log messages.
|
||||
if (actualSent < txBufferSize)
|
||||
// Some log messages.
|
||||
if (actualSent < txBufferSize)
|
||||
{
|
||||
switch (m_txBuffer->GetBufferContentType(socket))
|
||||
{
|
||||
switch (m_txBuffer->GetBufferContentType(socket))
|
||||
{
|
||||
case ThreeGppHttpHeader::MAIN_OBJECT:
|
||||
NS_LOG_INFO(this << " Transmission of main object is suspended"
|
||||
<< " after " << actualSent << " bytes.");
|
||||
break;
|
||||
case ThreeGppHttpHeader::EMBEDDED_OBJECT:
|
||||
NS_LOG_INFO(this << " Transmission of embedded object is suspended"
|
||||
<< " after " << actualSent << " bytes.");
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR("Invalid Tx buffer content type.");
|
||||
break;
|
||||
}
|
||||
case ThreeGppHttpHeader::MAIN_OBJECT:
|
||||
NS_LOG_INFO(this << " Transmission of main object is suspended"
|
||||
<< " after " << actualSent << " bytes.");
|
||||
break;
|
||||
case ThreeGppHttpHeader::EMBEDDED_OBJECT:
|
||||
NS_LOG_INFO(this << " Transmission of embedded object is suspended"
|
||||
<< " after " << actualSent << " bytes.");
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR("Invalid Tx buffer content type.");
|
||||
break;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_txBuffer->GetBufferContentType(socket))
|
||||
{
|
||||
switch (m_txBuffer->GetBufferContentType(socket))
|
||||
{
|
||||
case ThreeGppHttpHeader::MAIN_OBJECT:
|
||||
NS_LOG_INFO(this << " Finished sending a whole main object.");
|
||||
break;
|
||||
case ThreeGppHttpHeader::EMBEDDED_OBJECT:
|
||||
NS_LOG_INFO(this << " Finished sending a whole embedded object.");
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR("Invalid Tx buffer content type.");
|
||||
break;
|
||||
}
|
||||
case ThreeGppHttpHeader::MAIN_OBJECT:
|
||||
NS_LOG_INFO(this << " Finished sending a whole main object.");
|
||||
break;
|
||||
case ThreeGppHttpHeader::EMBEDDED_OBJECT:
|
||||
NS_LOG_INFO(this << " Finished sending a whole embedded object.");
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR("Invalid Tx buffer content type.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* NS3_LOG_ENABLE */
|
||||
|
||||
} // end of `if (m_txBuffer->IsBufferEmpty (socket))`
|
||||
|
||||
} // end of `void SendCallback (Ptr<Socket> socket, uint32_t availableBufferSize)`
|
||||
|
||||
void
|
||||
|
||||
@@ -453,28 +453,30 @@ CheckEnvironmentVariables()
|
||||
<< "\" in env variable NS_LOG, see above for a list of valid components");
|
||||
}
|
||||
|
||||
// We have a valid component or wildcard, check the flags
|
||||
if (!value.empty())
|
||||
// No valid component or wildcard
|
||||
if (value.empty())
|
||||
{
|
||||
// Check the flags present in value
|
||||
StringVector flags = SplitString(value, "|");
|
||||
for (const auto& flag : flags)
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have a valid component or wildcard, check the flags present in value
|
||||
StringVector flags = SplitString(value, "|");
|
||||
for (const auto& flag : flags)
|
||||
{
|
||||
// Handle wild cards
|
||||
if (flag == "*" || flag == "**")
|
||||
{
|
||||
// Handle wild cards
|
||||
if (flag == "*" || flag == "**")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool ok = LOG_LABEL_LEVELS.find(flag) != LOG_LABEL_LEVELS.end();
|
||||
if (!ok)
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid log level \""
|
||||
<< flag << "\" in env variable NS_LOG for component name "
|
||||
<< component);
|
||||
}
|
||||
} // for flag
|
||||
} // !value.empty
|
||||
} // for component
|
||||
continue;
|
||||
}
|
||||
bool ok = LOG_LABEL_LEVELS.find(flag) != LOG_LABEL_LEVELS.end();
|
||||
if (!ok)
|
||||
{
|
||||
NS_FATAL_ERROR("Invalid log level \""
|
||||
<< flag << "\" in env variable NS_LOG for component name "
|
||||
<< component);
|
||||
}
|
||||
} // for flag
|
||||
} // for component
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1559,77 +1559,79 @@ GlobalRouteManagerImpl::SPFAddASExternal(GlobalRoutingLSA* extlsa, SPFVertex* v)
|
||||
//
|
||||
NS_LOG_LOGIC("Considering router " << rtr->GetRouterId());
|
||||
|
||||
if (rtr->GetRouterId() == routerId)
|
||||
if (rtr->GetRouterId() != routerId)
|
||||
{
|
||||
NS_LOG_LOGIC("Setting routes for node " << node->GetId());
|
||||
//
|
||||
// Routing information is updated using the Ipv4 interface. We need to QI
|
||||
// for that interface. If the node is acting as an IP version 4 router, it
|
||||
// should absolutely have an Ipv4 interface.
|
||||
//
|
||||
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
|
||||
NS_ASSERT_MSG(ipv4,
|
||||
"GlobalRouteManagerImpl::SPFIntraAddRouter (): "
|
||||
"QI for <Ipv4> interface failed");
|
||||
//
|
||||
// Get the Global Router Link State Advertisement from the vertex we're
|
||||
// adding the routes to. The LSA will have a number of attached Global Router
|
||||
// Link Records corresponding to links off of that vertex / node. We're going
|
||||
// to be interested in the records corresponding to point-to-point links.
|
||||
//
|
||||
NS_ASSERT_MSG(v->GetLSA(),
|
||||
"GlobalRouteManagerImpl::SPFIntraAddRouter (): "
|
||||
"Expected valid LSA in SPFVertex* v");
|
||||
Ipv4Mask tempmask = extlsa->GetNetworkLSANetworkMask();
|
||||
Ipv4Address tempip = extlsa->GetLinkStateId();
|
||||
tempip = tempip.CombineMask(tempmask);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Here's why we did all of that work. We're going to add a host route to the
|
||||
// host address found in the m_linkData field of the point-to-point link
|
||||
// record. In the case of a point-to-point link, this is the local IP address
|
||||
// of the node connected to the link. Each of these point-to-point links
|
||||
// will correspond to a local interface that has an IP address to which
|
||||
// the node at the root of the SPF tree can send packets. The vertex <v>
|
||||
// (corresponding to the node that has these links and interfaces) has
|
||||
// an m_nextHop address precalculated for us that is the address to which the
|
||||
// root node should send packets to be forwarded to these IP addresses.
|
||||
// Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
|
||||
// which the packets should be send for forwarding.
|
||||
//
|
||||
Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
|
||||
if (!router)
|
||||
NS_LOG_LOGIC("Setting routes for node " << node->GetId());
|
||||
//
|
||||
// Routing information is updated using the Ipv4 interface. We need to QI
|
||||
// for that interface. If the node is acting as an IP version 4 router, it
|
||||
// should absolutely have an Ipv4 interface.
|
||||
//
|
||||
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
|
||||
NS_ASSERT_MSG(ipv4,
|
||||
"GlobalRouteManagerImpl::SPFIntraAddRouter (): "
|
||||
"QI for <Ipv4> interface failed");
|
||||
//
|
||||
// Get the Global Router Link State Advertisement from the vertex we're
|
||||
// adding the routes to. The LSA will have a number of attached Global Router
|
||||
// Link Records corresponding to links off of that vertex / node. We're going
|
||||
// to be interested in the records corresponding to point-to-point links.
|
||||
//
|
||||
NS_ASSERT_MSG(v->GetLSA(),
|
||||
"GlobalRouteManagerImpl::SPFIntraAddRouter (): "
|
||||
"Expected valid LSA in SPFVertex* v");
|
||||
Ipv4Mask tempmask = extlsa->GetNetworkLSANetworkMask();
|
||||
Ipv4Address tempip = extlsa->GetLinkStateId();
|
||||
tempip = tempip.CombineMask(tempmask);
|
||||
|
||||
//
|
||||
// Here's why we did all of that work. We're going to add a host route to the
|
||||
// host address found in the m_linkData field of the point-to-point link
|
||||
// record. In the case of a point-to-point link, this is the local IP address
|
||||
// of the node connected to the link. Each of these point-to-point links
|
||||
// will correspond to a local interface that has an IP address to which
|
||||
// the node at the root of the SPF tree can send packets. The vertex <v>
|
||||
// (corresponding to the node that has these links and interfaces) has
|
||||
// an m_nextHop address precalculated for us that is the address to which the
|
||||
// root node should send packets to be forwarded to these IP addresses.
|
||||
// Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
|
||||
// which the packets should be send for forwarding.
|
||||
//
|
||||
Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
|
||||
if (!router)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol();
|
||||
NS_ASSERT(gr);
|
||||
// walk through all next-hop-IPs and out-going-interfaces for reaching
|
||||
// the stub network gateway 'v' from the root node
|
||||
for (uint32_t i = 0; i < v->GetNRootExitDirections(); i++)
|
||||
{
|
||||
SPFVertex::NodeExit_t exit = v->GetRootExitDirection(i);
|
||||
Ipv4Address nextHop = exit.first;
|
||||
int32_t outIf = exit.second;
|
||||
if (outIf >= 0)
|
||||
{
|
||||
continue;
|
||||
gr->AddASExternalRouteTo(tempip, tempmask, nextHop, outIf);
|
||||
NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
|
||||
<< " add external network route to " << tempip
|
||||
<< " using next hop " << nextHop << " via interface "
|
||||
<< outIf);
|
||||
}
|
||||
Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol();
|
||||
NS_ASSERT(gr);
|
||||
// walk through all next-hop-IPs and out-going-interfaces for reaching
|
||||
// the stub network gateway 'v' from the root node
|
||||
for (uint32_t i = 0; i < v->GetNRootExitDirections(); i++)
|
||||
else
|
||||
{
|
||||
SPFVertex::NodeExit_t exit = v->GetRootExitDirection(i);
|
||||
Ipv4Address nextHop = exit.first;
|
||||
int32_t outIf = exit.second;
|
||||
if (outIf >= 0)
|
||||
{
|
||||
gr->AddASExternalRouteTo(tempip, tempmask, nextHop, outIf);
|
||||
NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
|
||||
<< " add external network route to " << tempip
|
||||
<< " using next hop " << nextHop << " via interface "
|
||||
<< outIf);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
|
||||
<< " NOT able to add network route to " << tempip
|
||||
<< " using next hop " << nextHop
|
||||
<< " since outgoing interface id is negative");
|
||||
}
|
||||
NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
|
||||
<< " NOT able to add network route to " << tempip
|
||||
<< " using next hop " << nextHop
|
||||
<< " since outgoing interface id is negative");
|
||||
}
|
||||
return;
|
||||
} // if
|
||||
} // for
|
||||
}
|
||||
return;
|
||||
} // for
|
||||
}
|
||||
|
||||
// Processing logic from RFC 2328, page 166 and quagga ospf_spf_process_stubs ()
|
||||
@@ -1930,102 +1932,103 @@ GlobalRouteManagerImpl::SPFIntraAddRouter(SPFVertex* v)
|
||||
//
|
||||
NS_LOG_LOGIC("Considering router " << rtr->GetRouterId());
|
||||
|
||||
if (rtr->GetRouterId() == routerId)
|
||||
if (rtr->GetRouterId() != routerId)
|
||||
{
|
||||
NS_LOG_LOGIC("Setting routes for node " << node->GetId());
|
||||
//
|
||||
// Routing information is updated using the Ipv4 interface. We need to
|
||||
// GetObject for that interface. If the node is acting as an IP version 4
|
||||
// router, it should absolutely have an Ipv4 interface.
|
||||
//
|
||||
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
|
||||
NS_ASSERT_MSG(ipv4,
|
||||
"GlobalRouteManagerImpl::SPFIntraAddRouter (): "
|
||||
"GetObject for <Ipv4> interface failed");
|
||||
//
|
||||
// Get the Global Router Link State Advertisement from the vertex we're
|
||||
// adding the routes to. The LSA will have a number of attached Global Router
|
||||
// Link Records corresponding to links off of that vertex / node. We're going
|
||||
// to be interested in the records corresponding to point-to-point links.
|
||||
//
|
||||
GlobalRoutingLSA* lsa = v->GetLSA();
|
||||
NS_ASSERT_MSG(lsa,
|
||||
"GlobalRouteManagerImpl::SPFIntraAddRouter (): "
|
||||
"Expected valid LSA in SPFVertex* v");
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t nLinkRecords = lsa->GetNLinkRecords();
|
||||
NS_LOG_LOGIC("Setting routes for node " << node->GetId());
|
||||
//
|
||||
// Routing information is updated using the Ipv4 interface. We need to
|
||||
// GetObject for that interface. If the node is acting as an IP version 4
|
||||
// router, it should absolutely have an Ipv4 interface.
|
||||
//
|
||||
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
|
||||
NS_ASSERT_MSG(ipv4,
|
||||
"GlobalRouteManagerImpl::SPFIntraAddRouter (): "
|
||||
"GetObject for <Ipv4> interface failed");
|
||||
//
|
||||
// Get the Global Router Link State Advertisement from the vertex we're
|
||||
// adding the routes to. The LSA will have a number of attached Global Router
|
||||
// Link Records corresponding to links off of that vertex / node. We're going
|
||||
// to be interested in the records corresponding to point-to-point links.
|
||||
//
|
||||
GlobalRoutingLSA* lsa = v->GetLSA();
|
||||
NS_ASSERT_MSG(lsa,
|
||||
"GlobalRouteManagerImpl::SPFIntraAddRouter (): "
|
||||
"Expected valid LSA in SPFVertex* v");
|
||||
|
||||
uint32_t nLinkRecords = lsa->GetNLinkRecords();
|
||||
//
|
||||
// Iterate through the link records on the vertex to which we're going to add
|
||||
// routes. To make sure we're being clear, we're going to add routing table
|
||||
// entries to the tables on the node corresponding to the root of the SPF tree.
|
||||
// These entries will have routes to the IP addresses we find from looking at
|
||||
// the local side of the point-to-point links found on the node described by
|
||||
// the vertex <v>.
|
||||
//
|
||||
NS_LOG_LOGIC(" Node " << node->GetId() << " found " << nLinkRecords
|
||||
<< " link records in LSA " << lsa << "with LinkStateId "
|
||||
<< lsa->GetLinkStateId());
|
||||
for (uint32_t j = 0; j < nLinkRecords; ++j)
|
||||
{
|
||||
//
|
||||
// Iterate through the link records on the vertex to which we're going to add
|
||||
// routes. To make sure we're being clear, we're going to add routing table
|
||||
// entries to the tables on the node corresponding to the root of the SPF tree.
|
||||
// These entries will have routes to the IP addresses we find from looking at
|
||||
// the local side of the point-to-point links found on the node described by
|
||||
// the vertex <v>.
|
||||
// We are only concerned about point-to-point links
|
||||
//
|
||||
NS_LOG_LOGIC(" Node " << node->GetId() << " found " << nLinkRecords
|
||||
<< " link records in LSA " << lsa << "with LinkStateId "
|
||||
<< lsa->GetLinkStateId());
|
||||
for (uint32_t j = 0; j < nLinkRecords; ++j)
|
||||
GlobalRoutingLinkRecord* lr = lsa->GetLinkRecord(j);
|
||||
if (lr->GetLinkType() != GlobalRoutingLinkRecord::PointToPoint)
|
||||
{
|
||||
//
|
||||
// We are only concerned about point-to-point links
|
||||
//
|
||||
GlobalRoutingLinkRecord* lr = lsa->GetLinkRecord(j);
|
||||
if (lr->GetLinkType() != GlobalRoutingLinkRecord::PointToPoint)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Here's why we did all of that work. We're going to add a host route to the
|
||||
// host address found in the m_linkData field of the point-to-point link
|
||||
// record. In the case of a point-to-point link, this is the local IP address
|
||||
// of the node connected to the link. Each of these point-to-point links
|
||||
// will correspond to a local interface that has an IP address to which
|
||||
// the node at the root of the SPF tree can send packets. The vertex <v>
|
||||
// (corresponding to the node that has these links and interfaces) has
|
||||
// an m_nextHop address precalculated for us that is the address to which the
|
||||
// root node should send packets to be forwarded to these IP addresses.
|
||||
// Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
|
||||
// which the packets should be send for forwarding.
|
||||
//
|
||||
Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
|
||||
if (!router)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol();
|
||||
NS_ASSERT(gr);
|
||||
// walk through all available exit directions due to ECMP,
|
||||
// and add host route for each of the exit direction toward
|
||||
// the vertex 'v'
|
||||
for (uint32_t i = 0; i < v->GetNRootExitDirections(); i++)
|
||||
{
|
||||
SPFVertex::NodeExit_t exit = v->GetRootExitDirection(i);
|
||||
Ipv4Address nextHop = exit.first;
|
||||
int32_t outIf = exit.second;
|
||||
if (outIf >= 0)
|
||||
{
|
||||
gr->AddHostRouteTo(lr->GetLinkData(), nextHop, outIf);
|
||||
NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
|
||||
<< " adding host route to " << lr->GetLinkData()
|
||||
<< " using next hop " << nextHop
|
||||
<< " and outgoing interface " << outIf);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
|
||||
<< " NOT able to add host route to "
|
||||
<< lr->GetLinkData() << " using next hop " << nextHop
|
||||
<< " since outgoing interface id is negative "
|
||||
<< outIf);
|
||||
}
|
||||
} // for all routes from the root the vertex 'v'
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Done adding the routes for the selected node.
|
||||
// Here's why we did all of that work. We're going to add a host route to the
|
||||
// host address found in the m_linkData field of the point-to-point link
|
||||
// record. In the case of a point-to-point link, this is the local IP address
|
||||
// of the node connected to the link. Each of these point-to-point links
|
||||
// will correspond to a local interface that has an IP address to which
|
||||
// the node at the root of the SPF tree can send packets. The vertex <v>
|
||||
// (corresponding to the node that has these links and interfaces) has
|
||||
// an m_nextHop address precalculated for us that is the address to which the
|
||||
// root node should send packets to be forwarded to these IP addresses.
|
||||
// Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
|
||||
// which the packets should be send for forwarding.
|
||||
//
|
||||
return;
|
||||
Ptr<GlobalRouter> router = node->GetObject<GlobalRouter>();
|
||||
if (!router)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol();
|
||||
NS_ASSERT(gr);
|
||||
// walk through all available exit directions due to ECMP,
|
||||
// and add host route for each of the exit direction toward
|
||||
// the vertex 'v'
|
||||
for (uint32_t i = 0; i < v->GetNRootExitDirections(); i++)
|
||||
{
|
||||
SPFVertex::NodeExit_t exit = v->GetRootExitDirection(i);
|
||||
Ipv4Address nextHop = exit.first;
|
||||
int32_t outIf = exit.second;
|
||||
if (outIf >= 0)
|
||||
{
|
||||
gr->AddHostRouteTo(lr->GetLinkData(), nextHop, outIf);
|
||||
NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
|
||||
<< " adding host route to " << lr->GetLinkData()
|
||||
<< " using next hop " << nextHop
|
||||
<< " and outgoing interface " << outIf);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_LOGIC("(Route " << i << ") Node " << node->GetId()
|
||||
<< " NOT able to add host route to " << lr->GetLinkData()
|
||||
<< " using next hop " << nextHop
|
||||
<< " since outgoing interface id is negative " << outIf);
|
||||
}
|
||||
} // for all routes from the root the vertex 'v'
|
||||
}
|
||||
//
|
||||
// Done adding the routes for the selected node.
|
||||
//
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,45 +119,43 @@ A3RsrpHandoverAlgorithm::DoReportUeMeas(uint16_t rnti, LteRrcSap::MeasResults me
|
||||
return;
|
||||
}
|
||||
|
||||
if (measResults.haveMeasResultNeighCells && !measResults.measResultListEutra.empty())
|
||||
{
|
||||
uint16_t bestNeighbourCellId = 0;
|
||||
uint8_t bestNeighbourRsrp = 0;
|
||||
|
||||
for (auto it = measResults.measResultListEutra.begin();
|
||||
it != measResults.measResultListEutra.end();
|
||||
++it)
|
||||
{
|
||||
if (it->haveRsrpResult)
|
||||
{
|
||||
if ((bestNeighbourRsrp < it->rsrpResult) && IsValidNeighbour(it->physCellId))
|
||||
{
|
||||
bestNeighbourCellId = it->physCellId;
|
||||
bestNeighbourRsrp = it->rsrpResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN("RSRP measurement is missing from cell ID " << it->physCellId);
|
||||
}
|
||||
}
|
||||
|
||||
if (bestNeighbourCellId > 0)
|
||||
{
|
||||
NS_LOG_LOGIC("Trigger Handover to cellId " << bestNeighbourCellId);
|
||||
NS_LOG_LOGIC("target cell RSRP " << (uint16_t)bestNeighbourRsrp);
|
||||
NS_LOG_LOGIC("serving cell RSRP " << (uint16_t)measResults.measResultPCell.rsrpResult);
|
||||
|
||||
// Inform eNodeB RRC about handover
|
||||
m_handoverManagementSapUser->TriggerHandover(rnti, bestNeighbourCellId);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!measResults.haveMeasResultNeighCells || measResults.measResultListEutra.empty())
|
||||
{
|
||||
NS_LOG_WARN(
|
||||
this << " Event A3 received without measurement results from neighbouring cells");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t bestNeighbourCellId = 0;
|
||||
uint8_t bestNeighbourRsrp = 0;
|
||||
|
||||
for (auto it = measResults.measResultListEutra.begin();
|
||||
it != measResults.measResultListEutra.end();
|
||||
++it)
|
||||
{
|
||||
if (it->haveRsrpResult)
|
||||
{
|
||||
if ((bestNeighbourRsrp < it->rsrpResult) && IsValidNeighbour(it->physCellId))
|
||||
{
|
||||
bestNeighbourCellId = it->physCellId;
|
||||
bestNeighbourRsrp = it->rsrpResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN("RSRP measurement is missing from cell ID " << it->physCellId);
|
||||
}
|
||||
}
|
||||
|
||||
if (bestNeighbourCellId > 0)
|
||||
{
|
||||
NS_LOG_LOGIC("Trigger Handover to cellId " << bestNeighbourCellId);
|
||||
NS_LOG_LOGIC("target cell RSRP " << (uint16_t)bestNeighbourRsrp);
|
||||
NS_LOG_LOGIC("serving cell RSRP " << (uint16_t)measResults.measResultPCell.rsrpResult);
|
||||
|
||||
// Inform eNodeB RRC about handover
|
||||
m_handoverManagementSapUser->TriggerHandover(rnti, bestNeighbourCellId);
|
||||
}
|
||||
} // end of DoReportUeMeas
|
||||
|
||||
bool
|
||||
|
||||
@@ -843,111 +843,112 @@ FdMtFfMacScheduler::DoSchedDlTriggerReq(
|
||||
for (int i = 0; i < rbgNum; i++)
|
||||
{
|
||||
NS_LOG_INFO(this << " ALLOCATION for RBG " << i << " of " << rbgNum);
|
||||
if (!rbgMap.at(i))
|
||||
if (rbgMap.at(i))
|
||||
{
|
||||
auto itMax = m_flowStatsDl.end();
|
||||
double rcqiMax = 0.0;
|
||||
for (auto it = m_flowStatsDl.begin(); it != m_flowStatsDl.end(); it++)
|
||||
continue;
|
||||
}
|
||||
|
||||
auto itMax = m_flowStatsDl.end();
|
||||
double rcqiMax = 0.0;
|
||||
for (auto it = m_flowStatsDl.begin(); it != m_flowStatsDl.end(); it++)
|
||||
{
|
||||
auto itRnti = rntiAllocated.find(*it);
|
||||
if (itRnti != rntiAllocated.end() || !HarqProcessAvailability(*it))
|
||||
{
|
||||
auto itRnti = rntiAllocated.find(*it);
|
||||
if (itRnti != rntiAllocated.end() || !HarqProcessAvailability(*it))
|
||||
// UE already allocated for HARQ or without HARQ process available -> drop it
|
||||
if (itRnti != rntiAllocated.end())
|
||||
{
|
||||
// UE already allocated for HARQ or without HARQ process available -> drop it
|
||||
if (itRnti != rntiAllocated.end())
|
||||
{
|
||||
NS_LOG_DEBUG(this << " RNTI discarded for HARQ tx" << (uint16_t)(*it));
|
||||
}
|
||||
if (!HarqProcessAvailability(*it))
|
||||
{
|
||||
NS_LOG_DEBUG(this << " RNTI discarded for HARQ id" << (uint16_t)(*it));
|
||||
}
|
||||
continue;
|
||||
NS_LOG_DEBUG(this << " RNTI discarded for HARQ tx" << (uint16_t)(*it));
|
||||
}
|
||||
|
||||
auto itCqi = m_a30CqiRxed.find(*it);
|
||||
auto itTxMode = m_uesTxMode.find(*it);
|
||||
if (itTxMode == m_uesTxMode.end())
|
||||
if (!HarqProcessAvailability(*it))
|
||||
{
|
||||
NS_FATAL_ERROR("No Transmission Mode info on user " << (*it));
|
||||
NS_LOG_DEBUG(this << " RNTI discarded for HARQ id" << (uint16_t)(*it));
|
||||
}
|
||||
auto nLayer = TransmissionModesLayers::TxMode2LayerNum((*itTxMode).second);
|
||||
std::vector<uint8_t> sbCqi;
|
||||
if (itCqi == m_a30CqiRxed.end())
|
||||
{
|
||||
sbCqi = std::vector<uint8_t>(nLayer, 1); // start with lowest value
|
||||
}
|
||||
else
|
||||
{
|
||||
sbCqi = (*itCqi).second.m_higherLayerSelected.at(i).m_sbCqi;
|
||||
}
|
||||
uint8_t cqi1 = sbCqi.at(0);
|
||||
uint8_t cqi2 = 0;
|
||||
if (sbCqi.size() > 1)
|
||||
{
|
||||
cqi2 = sbCqi.at(1);
|
||||
}
|
||||
if ((cqi1 > 0) ||
|
||||
(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
|
||||
{
|
||||
if (LcActivePerFlow(*it) > 0)
|
||||
{
|
||||
// this UE has data to transmit
|
||||
double achievableRate = 0.0;
|
||||
uint8_t mcs = 0;
|
||||
for (uint8_t k = 0; k < nLayer; k++)
|
||||
{
|
||||
if (sbCqi.size() > k)
|
||||
{
|
||||
mcs = m_amc->GetMcsFromCqi(sbCqi.at(k));
|
||||
}
|
||||
else
|
||||
{
|
||||
// no info on this subband -> worst MCS
|
||||
mcs = 0;
|
||||
}
|
||||
achievableRate += ((m_amc->GetDlTbSizeFromMcs(mcs, rbgSize) / 8) /
|
||||
0.001); // = TB size / TTI
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
double rcqi = achievableRate;
|
||||
NS_LOG_INFO(this << " RNTI " << (*it) << " MCS " << (uint32_t)mcs
|
||||
<< " achievableRate " << achievableRate << " RCQI "
|
||||
<< rcqi);
|
||||
|
||||
if (rcqi > rcqiMax)
|
||||
{
|
||||
rcqiMax = rcqi;
|
||||
itMax = it;
|
||||
}
|
||||
}
|
||||
} // end if cqi
|
||||
|
||||
} // end for m_rlcBufferReq
|
||||
|
||||
if (itMax == m_flowStatsDl.end())
|
||||
auto itCqi = m_a30CqiRxed.find(*it);
|
||||
auto itTxMode = m_uesTxMode.find(*it);
|
||||
if (itTxMode == m_uesTxMode.end())
|
||||
{
|
||||
// no UE available for this RB
|
||||
NS_LOG_INFO(this << " any UE found");
|
||||
NS_FATAL_ERROR("No Transmission Mode info on user " << (*it));
|
||||
}
|
||||
auto nLayer = TransmissionModesLayers::TxMode2LayerNum((*itTxMode).second);
|
||||
std::vector<uint8_t> sbCqi;
|
||||
if (itCqi == m_a30CqiRxed.end())
|
||||
{
|
||||
sbCqi = std::vector<uint8_t>(nLayer, 1); // start with lowest value
|
||||
}
|
||||
else
|
||||
{
|
||||
rbgMap.at(i) = true;
|
||||
auto itMap = allocationMap.find(*itMax);
|
||||
if (itMap == allocationMap.end())
|
||||
{
|
||||
// insert new element
|
||||
std::vector<uint16_t> tempMap;
|
||||
tempMap.push_back(i);
|
||||
allocationMap[*itMax] = tempMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*itMap).second.push_back(i);
|
||||
}
|
||||
NS_LOG_INFO(this << " UE assigned " << (*itMax));
|
||||
sbCqi = (*itCqi).second.m_higherLayerSelected.at(i).m_sbCqi;
|
||||
}
|
||||
} // end for RBG free
|
||||
} // end for RBGs
|
||||
uint8_t cqi1 = sbCqi.at(0);
|
||||
uint8_t cqi2 = 0;
|
||||
if (sbCqi.size() > 1)
|
||||
{
|
||||
cqi2 = sbCqi.at(1);
|
||||
}
|
||||
if ((cqi1 > 0) ||
|
||||
(cqi2 > 0)) // CQI == 0 means "out of range" (see table 7.2.3-1 of 36.213)
|
||||
{
|
||||
if (LcActivePerFlow(*it) > 0)
|
||||
{
|
||||
// this UE has data to transmit
|
||||
double achievableRate = 0.0;
|
||||
uint8_t mcs = 0;
|
||||
for (uint8_t k = 0; k < nLayer; k++)
|
||||
{
|
||||
if (sbCqi.size() > k)
|
||||
{
|
||||
mcs = m_amc->GetMcsFromCqi(sbCqi.at(k));
|
||||
}
|
||||
else
|
||||
{
|
||||
// no info on this subband -> worst MCS
|
||||
mcs = 0;
|
||||
}
|
||||
achievableRate += ((m_amc->GetDlTbSizeFromMcs(mcs, rbgSize) / 8) /
|
||||
0.001); // = TB size / TTI
|
||||
}
|
||||
|
||||
double rcqi = achievableRate;
|
||||
NS_LOG_INFO(this << " RNTI " << (*it) << " MCS " << (uint32_t)mcs
|
||||
<< " achievableRate " << achievableRate << " RCQI " << rcqi);
|
||||
|
||||
if (rcqi > rcqiMax)
|
||||
{
|
||||
rcqiMax = rcqi;
|
||||
itMax = it;
|
||||
}
|
||||
}
|
||||
} // end if cqi
|
||||
|
||||
} // end for m_rlcBufferReq
|
||||
|
||||
if (itMax == m_flowStatsDl.end())
|
||||
{
|
||||
// no UE available for this RB
|
||||
NS_LOG_INFO(this << " any UE found");
|
||||
}
|
||||
else
|
||||
{
|
||||
rbgMap.at(i) = true;
|
||||
auto itMap = allocationMap.find(*itMax);
|
||||
if (itMap == allocationMap.end())
|
||||
{
|
||||
// insert new element
|
||||
std::vector<uint16_t> tempMap;
|
||||
tempMap.push_back(i);
|
||||
allocationMap[*itMax] = tempMap;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*itMap).second.push_back(i);
|
||||
}
|
||||
NS_LOG_INFO(this << " UE assigned " << (*itMax));
|
||||
}
|
||||
} // end for RBGs
|
||||
|
||||
// generate the transmission opportunities by grouping the RBGs of the same RNTI and
|
||||
// creating the correspondent DCIs
|
||||
@@ -1207,25 +1208,23 @@ FdMtFfMacScheduler::EstimateUlSinr(uint16_t rnti, uint16_t rb)
|
||||
// no cqi info about this UE
|
||||
return NO_SINR;
|
||||
}
|
||||
else
|
||||
|
||||
// take the average SINR value among the available
|
||||
double sinrSum = 0;
|
||||
unsigned int sinrNum = 0;
|
||||
for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
|
||||
{
|
||||
// take the average SINR value among the available
|
||||
double sinrSum = 0;
|
||||
unsigned int sinrNum = 0;
|
||||
for (uint32_t i = 0; i < m_cschedCellConfig.m_ulBandwidth; i++)
|
||||
double sinr = (*itCqi).second.at(i);
|
||||
if (sinr != NO_SINR)
|
||||
{
|
||||
double sinr = (*itCqi).second.at(i);
|
||||
if (sinr != NO_SINR)
|
||||
{
|
||||
sinrSum += sinr;
|
||||
sinrNum++;
|
||||
}
|
||||
sinrSum += sinr;
|
||||
sinrNum++;
|
||||
}
|
||||
double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
|
||||
// store the value
|
||||
(*itCqi).second.at(rb) = estimatedSinr;
|
||||
return estimatedSinr;
|
||||
}
|
||||
double estimatedSinr = (sinrNum > 0) ? (sinrSum / sinrNum) : DBL_MAX;
|
||||
// store the value
|
||||
(*itCqi).second.at(rb) = estimatedSinr;
|
||||
return estimatedSinr;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -1029,127 +1029,125 @@ LteSpectrumPhy::EndRxData()
|
||||
itTb = m_expectedTbs.find(tbId);
|
||||
NS_LOG_INFO(this << " Packet of " << tbId.m_rnti << " layer "
|
||||
<< (uint16_t)tag.GetLayer());
|
||||
if (itTb != m_expectedTbs.end())
|
||||
if (itTb == m_expectedTbs.end())
|
||||
{
|
||||
if (!(*itTb).second.corrupt)
|
||||
{
|
||||
m_phyRxEndOkTrace(*j);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_ltePhyRxDataEndOkCallback.IsNull())
|
||||
{
|
||||
m_ltePhyRxDataEndOkCallback(*j);
|
||||
}
|
||||
if (!(*itTb).second.corrupt)
|
||||
{
|
||||
m_phyRxEndOkTrace(*j);
|
||||
|
||||
if (!m_ltePhyRxDataEndOkCallback.IsNull())
|
||||
{
|
||||
m_ltePhyRxDataEndOkCallback(*j);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TB received with errors
|
||||
m_phyRxEndErrorTrace(*j);
|
||||
}
|
||||
|
||||
// send HARQ feedback (if not already done for this TB)
|
||||
if ((*itTb).second.harqFeedbackSent)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
(*itTb).second.harqFeedbackSent = true;
|
||||
if (!(*itTb).second.downlink)
|
||||
{
|
||||
UlInfoListElement_s harqUlInfo;
|
||||
harqUlInfo.m_rnti = tbId.m_rnti;
|
||||
harqUlInfo.m_tpc = 0;
|
||||
if ((*itTb).second.corrupt)
|
||||
{
|
||||
harqUlInfo.m_receptionStatus = UlInfoListElement_s::NotOk;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " send UL-HARQ-NACK");
|
||||
m_harqPhyModule->UpdateUlHarqProcessStatus(
|
||||
tbId.m_rnti,
|
||||
(*itTb).second.mi,
|
||||
(*itTb).second.size,
|
||||
(*itTb).second.size / EffectiveCodingRate[(*itTb).second.mcs]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TB received with errors
|
||||
m_phyRxEndErrorTrace(*j);
|
||||
harqUlInfo.m_receptionStatus = UlInfoListElement_s::Ok;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " send UL-HARQ-ACK");
|
||||
m_harqPhyModule->ResetUlHarqProcessStatus(tbId.m_rnti,
|
||||
(*itTb).second.harqProcessId);
|
||||
}
|
||||
|
||||
// send HARQ feedback (if not already done for this TB)
|
||||
if (!(*itTb).second.harqFeedbackSent)
|
||||
if (!m_ltePhyUlHarqFeedbackCallback.IsNull())
|
||||
{
|
||||
(*itTb).second.harqFeedbackSent = true;
|
||||
if (!(*itTb).second.downlink)
|
||||
m_ltePhyUlHarqFeedbackCallback(harqUlInfo);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto itHarq = harqDlInfoMap.find(tbId.m_rnti);
|
||||
if (itHarq == harqDlInfoMap.end())
|
||||
{
|
||||
DlInfoListElement_s harqDlInfo;
|
||||
harqDlInfo.m_harqStatus.resize(m_layersNum, DlInfoListElement_s::ACK);
|
||||
harqDlInfo.m_rnti = tbId.m_rnti;
|
||||
harqDlInfo.m_harqProcessId = (*itTb).second.harqProcessId;
|
||||
if ((*itTb).second.corrupt)
|
||||
{
|
||||
UlInfoListElement_s harqUlInfo;
|
||||
harqUlInfo.m_rnti = tbId.m_rnti;
|
||||
harqUlInfo.m_tpc = 0;
|
||||
if ((*itTb).second.corrupt)
|
||||
{
|
||||
harqUlInfo.m_receptionStatus = UlInfoListElement_s::NotOk;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " send UL-HARQ-NACK");
|
||||
m_harqPhyModule->UpdateUlHarqProcessStatus(
|
||||
tbId.m_rnti,
|
||||
(*itTb).second.mi,
|
||||
(*itTb).second.size,
|
||||
(*itTb).second.size / EffectiveCodingRate[(*itTb).second.mcs]);
|
||||
}
|
||||
else
|
||||
{
|
||||
harqUlInfo.m_receptionStatus = UlInfoListElement_s::Ok;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " send UL-HARQ-ACK");
|
||||
m_harqPhyModule->ResetUlHarqProcessStatus(tbId.m_rnti,
|
||||
(*itTb).second.harqProcessId);
|
||||
}
|
||||
if (!m_ltePhyUlHarqFeedbackCallback.IsNull())
|
||||
{
|
||||
m_ltePhyUlHarqFeedbackCallback(harqUlInfo);
|
||||
}
|
||||
harqDlInfo.m_harqStatus.at(tbId.m_layer) = DlInfoListElement_s::NACK;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " harqId "
|
||||
<< (uint16_t)(*itTb).second.harqProcessId << " layer "
|
||||
<< (uint16_t)tbId.m_layer << " send DL-HARQ-NACK");
|
||||
m_harqPhyModule->UpdateDlHarqProcessStatus(
|
||||
(*itTb).second.harqProcessId,
|
||||
tbId.m_layer,
|
||||
(*itTb).second.mi,
|
||||
(*itTb).second.size,
|
||||
(*itTb).second.size / EffectiveCodingRate[(*itTb).second.mcs]);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto itHarq = harqDlInfoMap.find(tbId.m_rnti);
|
||||
if (itHarq == harqDlInfoMap.end())
|
||||
{
|
||||
DlInfoListElement_s harqDlInfo;
|
||||
harqDlInfo.m_harqStatus.resize(m_layersNum, DlInfoListElement_s::ACK);
|
||||
harqDlInfo.m_rnti = tbId.m_rnti;
|
||||
harqDlInfo.m_harqProcessId = (*itTb).second.harqProcessId;
|
||||
if ((*itTb).second.corrupt)
|
||||
{
|
||||
harqDlInfo.m_harqStatus.at(tbId.m_layer) =
|
||||
DlInfoListElement_s::NACK;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " harqId "
|
||||
<< (uint16_t)(*itTb).second.harqProcessId
|
||||
<< " layer " << (uint16_t)tbId.m_layer
|
||||
<< " send DL-HARQ-NACK");
|
||||
m_harqPhyModule->UpdateDlHarqProcessStatus(
|
||||
(*itTb).second.harqProcessId,
|
||||
tbId.m_layer,
|
||||
(*itTb).second.mi,
|
||||
(*itTb).second.size,
|
||||
(*itTb).second.size / EffectiveCodingRate[(*itTb).second.mcs]);
|
||||
}
|
||||
else
|
||||
{
|
||||
harqDlInfo.m_harqStatus.at(tbId.m_layer) = DlInfoListElement_s::ACK;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " harqId "
|
||||
<< (uint16_t)(*itTb).second.harqProcessId
|
||||
<< " layer " << (uint16_t)tbId.m_layer << " size "
|
||||
<< (*itTb).second.size << " send DL-HARQ-ACK");
|
||||
m_harqPhyModule->ResetDlHarqProcessStatus(
|
||||
(*itTb).second.harqProcessId);
|
||||
}
|
||||
harqDlInfoMap.insert(
|
||||
std::pair<uint16_t, DlInfoListElement_s>(tbId.m_rnti, harqDlInfo));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*itTb).second.corrupt)
|
||||
{
|
||||
(*itHarq).second.m_harqStatus.at(tbId.m_layer) =
|
||||
DlInfoListElement_s::NACK;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " harqId "
|
||||
<< (uint16_t)(*itTb).second.harqProcessId
|
||||
<< " layer " << (uint16_t)tbId.m_layer << " size "
|
||||
<< (*itHarq).second.m_harqStatus.size()
|
||||
<< " send DL-HARQ-NACK");
|
||||
m_harqPhyModule->UpdateDlHarqProcessStatus(
|
||||
(*itTb).second.harqProcessId,
|
||||
tbId.m_layer,
|
||||
(*itTb).second.mi,
|
||||
(*itTb).second.size,
|
||||
(*itTb).second.size / EffectiveCodingRate[(*itTb).second.mcs]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERT_MSG(tbId.m_layer < (*itHarq).second.m_harqStatus.size(),
|
||||
" layer " << (uint16_t)tbId.m_layer);
|
||||
(*itHarq).second.m_harqStatus.at(tbId.m_layer) =
|
||||
DlInfoListElement_s::ACK;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " harqId "
|
||||
<< (uint16_t)(*itTb).second.harqProcessId
|
||||
<< " layer " << (uint16_t)tbId.m_layer << " size "
|
||||
<< (*itHarq).second.m_harqStatus.size()
|
||||
<< " send DL-HARQ-ACK");
|
||||
m_harqPhyModule->ResetDlHarqProcessStatus(
|
||||
(*itTb).second.harqProcessId);
|
||||
}
|
||||
}
|
||||
} // end if ((*itTb).second.downlink) HARQ
|
||||
} // end if (!(*itTb).second.harqFeedbackSent)
|
||||
}
|
||||
harqDlInfo.m_harqStatus.at(tbId.m_layer) = DlInfoListElement_s::ACK;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " harqId "
|
||||
<< (uint16_t)(*itTb).second.harqProcessId << " layer "
|
||||
<< (uint16_t)tbId.m_layer << " size "
|
||||
<< (*itTb).second.size << " send DL-HARQ-ACK");
|
||||
m_harqPhyModule->ResetDlHarqProcessStatus((*itTb).second.harqProcessId);
|
||||
}
|
||||
harqDlInfoMap.insert(
|
||||
std::pair<uint16_t, DlInfoListElement_s>(tbId.m_rnti, harqDlInfo));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*itTb).second.corrupt)
|
||||
{
|
||||
(*itHarq).second.m_harqStatus.at(tbId.m_layer) = DlInfoListElement_s::NACK;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " harqId "
|
||||
<< (uint16_t)(*itTb).second.harqProcessId << " layer "
|
||||
<< (uint16_t)tbId.m_layer << " size "
|
||||
<< (*itHarq).second.m_harqStatus.size()
|
||||
<< " send DL-HARQ-NACK");
|
||||
m_harqPhyModule->UpdateDlHarqProcessStatus(
|
||||
(*itTb).second.harqProcessId,
|
||||
tbId.m_layer,
|
||||
(*itTb).second.mi,
|
||||
(*itTb).second.size,
|
||||
(*itTb).second.size / EffectiveCodingRate[(*itTb).second.mcs]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERT_MSG(tbId.m_layer < (*itHarq).second.m_harqStatus.size(),
|
||||
" layer " << (uint16_t)tbId.m_layer);
|
||||
(*itHarq).second.m_harqStatus.at(tbId.m_layer) = DlInfoListElement_s::ACK;
|
||||
NS_LOG_DEBUG(this << " RNTI " << tbId.m_rnti << " harqId "
|
||||
<< (uint16_t)(*itTb).second.harqProcessId << " layer "
|
||||
<< (uint16_t)tbId.m_layer << " size "
|
||||
<< (*itHarq).second.m_harqStatus.size()
|
||||
<< " send DL-HARQ-ACK");
|
||||
m_harqPhyModule->ResetDlHarqProcessStatus((*itTb).second.harqProcessId);
|
||||
}
|
||||
}
|
||||
} // end if ((*itTb).second.downlink) HARQ
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -630,58 +630,59 @@ LteUePhy::GenerateCqiRsrpRsrq(const SpectrumValue& sinr)
|
||||
m_rsrpSinrSampleCounter = 0;
|
||||
}
|
||||
|
||||
if (m_pssReceived)
|
||||
if (!m_pssReceived)
|
||||
{
|
||||
// measure instantaneous RSRQ now
|
||||
NS_ASSERT_MSG(m_rsInterferencePowerUpdated, " RS interference power info obsolete");
|
||||
return;
|
||||
}
|
||||
|
||||
auto itPss = m_pssList.begin();
|
||||
while (itPss != m_pssList.end())
|
||||
// measure instantaneous RSRQ now
|
||||
NS_ASSERT_MSG(m_rsInterferencePowerUpdated, " RS interference power info obsolete");
|
||||
|
||||
auto itPss = m_pssList.begin();
|
||||
while (itPss != m_pssList.end())
|
||||
{
|
||||
uint16_t rbNum = 0;
|
||||
double rssiSum = 0.0;
|
||||
|
||||
auto itIntN = m_rsInterferencePower.ConstValuesBegin();
|
||||
auto itPj = m_rsReceivedPower.ConstValuesBegin();
|
||||
for (itPj = m_rsReceivedPower.ConstValuesBegin();
|
||||
itPj != m_rsReceivedPower.ConstValuesEnd();
|
||||
itIntN++, itPj++)
|
||||
{
|
||||
uint16_t rbNum = 0;
|
||||
double rssiSum = 0.0;
|
||||
rbNum++;
|
||||
// convert PSD [W/Hz] to linear power [W] for the single RE
|
||||
double interfPlusNoisePowerTxW = (*itIntN);
|
||||
double signalPowerTxW = (*itPj);
|
||||
rssiSum += (2 * (interfPlusNoisePowerTxW + signalPowerTxW));
|
||||
}
|
||||
rssiSum *= (180000.0 / 12.0);
|
||||
|
||||
auto itIntN = m_rsInterferencePower.ConstValuesBegin();
|
||||
auto itPj = m_rsReceivedPower.ConstValuesBegin();
|
||||
for (itPj = m_rsReceivedPower.ConstValuesBegin();
|
||||
itPj != m_rsReceivedPower.ConstValuesEnd();
|
||||
itIntN++, itPj++)
|
||||
NS_ASSERT(rbNum == (*itPss).nRB);
|
||||
double rsrq_dB = 10 * log10((*itPss).pssPsdSum / rssiSum);
|
||||
|
||||
if (rsrq_dB > m_pssReceptionThreshold)
|
||||
{
|
||||
NS_LOG_INFO(this << " PSS RNTI " << m_rnti << " cellId " << m_cellId << " has RSRQ "
|
||||
<< rsrq_dB << " and RBnum " << rbNum);
|
||||
// store measurements
|
||||
auto itMeasMap = m_ueMeasurementsMap.find((*itPss).cellId);
|
||||
if (itMeasMap != m_ueMeasurementsMap.end())
|
||||
{
|
||||
rbNum++;
|
||||
// convert PSD [W/Hz] to linear power [W] for the single RE
|
||||
double interfPlusNoisePowerTxW = (*itIntN);
|
||||
double signalPowerTxW = (*itPj);
|
||||
rssiSum += (2 * (interfPlusNoisePowerTxW + signalPowerTxW));
|
||||
(*itMeasMap).second.rsrqSum += rsrq_dB;
|
||||
(*itMeasMap).second.rsrqNum++;
|
||||
}
|
||||
rssiSum *= (180000.0 / 12.0);
|
||||
|
||||
NS_ASSERT(rbNum == (*itPss).nRB);
|
||||
double rsrq_dB = 10 * log10((*itPss).pssPsdSum / rssiSum);
|
||||
|
||||
if (rsrq_dB > m_pssReceptionThreshold)
|
||||
else
|
||||
{
|
||||
NS_LOG_INFO(this << " PSS RNTI " << m_rnti << " cellId " << m_cellId << " has RSRQ "
|
||||
<< rsrq_dB << " and RBnum " << rbNum);
|
||||
// store measurements
|
||||
auto itMeasMap = m_ueMeasurementsMap.find((*itPss).cellId);
|
||||
if (itMeasMap != m_ueMeasurementsMap.end())
|
||||
{
|
||||
(*itMeasMap).second.rsrqSum += rsrq_dB;
|
||||
(*itMeasMap).second.rsrqNum++;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_LOG_WARN("race condition of bug 2091 occurred");
|
||||
}
|
||||
NS_LOG_WARN("race condition of bug 2091 occurred");
|
||||
}
|
||||
}
|
||||
|
||||
itPss++;
|
||||
itPss++;
|
||||
|
||||
} // end of while (itPss != m_pssList.end ())
|
||||
} // end of while (itPss != m_pssList.end ())
|
||||
|
||||
m_pssList.clear();
|
||||
|
||||
} // end of if (m_pssReceived)
|
||||
m_pssList.clear();
|
||||
|
||||
} // end of void LteUePhy::GenerateCtrlCqiReport (const SpectrumValue& sinr)
|
||||
|
||||
|
||||
@@ -1571,81 +1571,82 @@ LteUeMeasurementsPiecewiseTestCase2::RecvMeasurementReportCallback(
|
||||
NS_ASSERT(rnti == 1);
|
||||
NS_ASSERT(cellId == 1);
|
||||
|
||||
if (report.measResults.measId == m_expectedMeasId)
|
||||
if (report.measResults.measId != m_expectedMeasId)
|
||||
{
|
||||
// verifying the report completeness
|
||||
LteRrcSap::MeasResults measResults = report.measResults;
|
||||
NS_LOG_DEBUG(
|
||||
this << " Serving cellId=" << cellId
|
||||
<< " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
|
||||
<< " dBm)"
|
||||
<< " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
|
||||
<< " dB)");
|
||||
return;
|
||||
}
|
||||
|
||||
// verifying reported best cells
|
||||
if (measResults.measResultListEutra.empty())
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
false,
|
||||
"Unexpected report content");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
true,
|
||||
"Unexpected report content");
|
||||
auto it = measResults.measResultListEutra.begin();
|
||||
NS_ASSERT(it != measResults.measResultListEutra.end());
|
||||
NS_ASSERT(it->physCellId == 2);
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveCgiInfo,
|
||||
false,
|
||||
"Report contains cgi-info, which is not supported");
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveRsrpResult,
|
||||
true,
|
||||
"Report does not contain measured RSRP result");
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveRsrqResult,
|
||||
true,
|
||||
"Report does not contain measured RSRQ result");
|
||||
NS_LOG_DEBUG(this << " Neighbour cellId=" << it->physCellId
|
||||
<< " rsrp=" << (uint16_t)it->rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(it->rsrpResult) << " dBm)"
|
||||
<< " rsrq=" << (uint16_t)it->rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(it->rsrqResult) << " dB)");
|
||||
// verifying the report completeness
|
||||
LteRrcSap::MeasResults measResults = report.measResults;
|
||||
NS_LOG_DEBUG(
|
||||
this << " Serving cellId=" << cellId
|
||||
<< " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
|
||||
<< " dBm)"
|
||||
<< " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
|
||||
<< " dB)");
|
||||
|
||||
} // end of else of if (measResults.measResultListEutra.size () == 0)
|
||||
|
||||
// verifying the report timing
|
||||
bool hasEnded = m_itExpectedTime == m_expectedTime.end();
|
||||
NS_TEST_ASSERT_MSG_EQ(hasEnded,
|
||||
// verifying reported best cells
|
||||
if (measResults.measResultListEutra.empty())
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
false,
|
||||
"Reporting should not have occurred at "
|
||||
<< Simulator::Now().As(Time::S));
|
||||
if (!hasEnded)
|
||||
{
|
||||
hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
|
||||
NS_ASSERT(!hasEnded);
|
||||
"Unexpected report content");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
true,
|
||||
"Unexpected report content");
|
||||
auto it = measResults.measResultListEutra.begin();
|
||||
NS_ASSERT(it != measResults.measResultListEutra.end());
|
||||
NS_ASSERT(it->physCellId == 2);
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveCgiInfo,
|
||||
false,
|
||||
"Report contains cgi-info, which is not supported");
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveRsrpResult,
|
||||
true,
|
||||
"Report does not contain measured RSRP result");
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveRsrqResult,
|
||||
true,
|
||||
"Report does not contain measured RSRQ result");
|
||||
NS_LOG_DEBUG(this << " Neighbour cellId=" << it->physCellId
|
||||
<< " rsrp=" << (uint16_t)it->rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(it->rsrpResult) << " dBm)"
|
||||
<< " rsrq=" << (uint16_t)it->rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(it->rsrqResult) << " dB)");
|
||||
|
||||
// using milliseconds to avoid floating-point comparison
|
||||
uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
|
||||
uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
|
||||
m_itExpectedTime++;
|
||||
} // end of else of if (measResults.measResultListEutra.size () == 0)
|
||||
|
||||
uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
|
||||
uint16_t referenceRsrp = *m_itExpectedRsrp;
|
||||
m_itExpectedRsrp++;
|
||||
// verifying the report timing
|
||||
bool hasEnded = m_itExpectedTime == m_expectedTime.end();
|
||||
NS_TEST_ASSERT_MSG_EQ(hasEnded,
|
||||
false,
|
||||
"Reporting should not have occurred at " << Simulator::Now().As(Time::S));
|
||||
if (hasEnded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ(timeNowMs,
|
||||
timeExpectedMs,
|
||||
"Reporting should not have occurred at this time");
|
||||
NS_TEST_ASSERT_MSG_EQ(observedRsrp,
|
||||
referenceRsrp,
|
||||
"The RSRP observed differs with the reference RSRP");
|
||||
hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
|
||||
NS_ASSERT(!hasEnded);
|
||||
|
||||
} // end of if (!hasEnded)
|
||||
// using milliseconds to avoid floating-point comparison
|
||||
uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
|
||||
uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
|
||||
m_itExpectedTime++;
|
||||
|
||||
} // end of if (report.measResults.measId == m_expectedMeasId)
|
||||
uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
|
||||
uint16_t referenceRsrp = *m_itExpectedRsrp;
|
||||
m_itExpectedRsrp++;
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ(timeNowMs,
|
||||
timeExpectedMs,
|
||||
"Reporting should not have occurred at this time");
|
||||
NS_TEST_ASSERT_MSG_EQ(observedRsrp,
|
||||
referenceRsrp,
|
||||
"The RSRP observed differs with the reference RSRP");
|
||||
|
||||
} // end of void LteUeMeasurementsPiecewiseTestCase2::RecvMeasurementReportCallback
|
||||
|
||||
@@ -1863,75 +1864,76 @@ LteUeMeasurementsPiecewiseTestCase3::RecvMeasurementReportCallback(
|
||||
NS_ASSERT(rnti == 1);
|
||||
NS_ASSERT(cellId == 1);
|
||||
|
||||
if (report.measResults.measId == m_expectedMeasId)
|
||||
if (report.measResults.measId != m_expectedMeasId)
|
||||
{
|
||||
// verifying the report completeness
|
||||
LteRrcSap::MeasResults measResults = report.measResults;
|
||||
NS_LOG_DEBUG(
|
||||
this << " Serving cellId=" << cellId
|
||||
<< " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
|
||||
<< " dBm)"
|
||||
<< " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
|
||||
<< " dB)");
|
||||
return;
|
||||
}
|
||||
|
||||
// verifying reported best cells
|
||||
if (measResults.measResultListEutra.empty())
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
false,
|
||||
"Unexpected report content");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
true,
|
||||
"Unexpected report content");
|
||||
auto it = measResults.measResultListEutra.begin();
|
||||
NS_ASSERT(it != measResults.measResultListEutra.end());
|
||||
for (const auto& it : measResults.measResultListEutra)
|
||||
{
|
||||
NS_ASSERT(it.physCellId == 2 || it.physCellId == 3);
|
||||
NS_TEST_ASSERT_MSG_EQ(it.haveCgiInfo,
|
||||
false,
|
||||
"Report contains cgi-info, which is not supported");
|
||||
NS_TEST_ASSERT_MSG_EQ(it.haveRsrpResult,
|
||||
true,
|
||||
"Report does not contain measured RSRP result");
|
||||
NS_TEST_ASSERT_MSG_EQ(it.haveRsrqResult,
|
||||
true,
|
||||
"Report does not contain measured RSRQ result");
|
||||
NS_LOG_DEBUG(
|
||||
this << " Neighbour cellId=" << it.physCellId
|
||||
<< " rsrp=" << (uint16_t)it.rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(it.rsrpResult) << " dBm)"
|
||||
<< " rsrq=" << (uint16_t)it.rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(it.rsrqResult) << " dB)");
|
||||
}
|
||||
// verifying the report completeness
|
||||
LteRrcSap::MeasResults measResults = report.measResults;
|
||||
NS_LOG_DEBUG(
|
||||
this << " Serving cellId=" << cellId
|
||||
<< " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
|
||||
<< " dBm)"
|
||||
<< " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
|
||||
<< " dB)");
|
||||
|
||||
} // end of else of if (measResults.measResultListEutra.size () == 0)
|
||||
|
||||
// verifying the report timing
|
||||
bool hasEnded = m_itExpectedTime == m_expectedTime.end();
|
||||
NS_TEST_ASSERT_MSG_EQ(hasEnded,
|
||||
// verifying reported best cells
|
||||
if (measResults.measResultListEutra.empty())
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
false,
|
||||
"Reporting should not have occurred at "
|
||||
<< Simulator::Now().GetSeconds() << "s");
|
||||
if (!hasEnded)
|
||||
"Unexpected report content");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
true,
|
||||
"Unexpected report content");
|
||||
auto it = measResults.measResultListEutra.begin();
|
||||
NS_ASSERT(it != measResults.measResultListEutra.end());
|
||||
for (const auto& it : measResults.measResultListEutra)
|
||||
{
|
||||
// using milliseconds to avoid floating-point comparison
|
||||
uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
|
||||
uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
|
||||
m_itExpectedTime++;
|
||||
NS_ASSERT(it.physCellId == 2 || it.physCellId == 3);
|
||||
NS_TEST_ASSERT_MSG_EQ(it.haveCgiInfo,
|
||||
false,
|
||||
"Report contains cgi-info, which is not supported");
|
||||
NS_TEST_ASSERT_MSG_EQ(it.haveRsrpResult,
|
||||
true,
|
||||
"Report does not contain measured RSRP result");
|
||||
NS_TEST_ASSERT_MSG_EQ(it.haveRsrqResult,
|
||||
true,
|
||||
"Report does not contain measured RSRQ result");
|
||||
NS_LOG_DEBUG(this << " Neighbour cellId=" << it.physCellId
|
||||
<< " rsrp=" << (uint16_t)it.rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(it.rsrpResult) << " dBm)"
|
||||
<< " rsrq=" << (uint16_t)it.rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(it.rsrqResult) << " dB)");
|
||||
}
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ(timeNowMs,
|
||||
timeExpectedMs,
|
||||
"Reporting should not have occurred at this time");
|
||||
} // end of else of if (measResults.measResultListEutra.size () == 0)
|
||||
|
||||
} // end of if (!hasEnded)
|
||||
// verifying the report timing
|
||||
bool hasEnded = m_itExpectedTime == m_expectedTime.end();
|
||||
NS_TEST_ASSERT_MSG_EQ(hasEnded,
|
||||
false,
|
||||
"Reporting should not have occurred at " << Simulator::Now().GetSeconds()
|
||||
<< "s");
|
||||
if (hasEnded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
} // end of if (report.measResults.measId == m_expectedMeasId)
|
||||
// using milliseconds to avoid floating-point comparison
|
||||
uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
|
||||
uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
|
||||
m_itExpectedTime++;
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ(timeNowMs,
|
||||
timeExpectedMs,
|
||||
"Reporting should not have occurred at this time");
|
||||
|
||||
} // end of void LteUeMeasurementsPiecewiseTestCase3::RecvMeasurementReportCallback
|
||||
|
||||
@@ -2491,81 +2493,82 @@ LteUeMeasurementsHandoverTestCase::RecvMeasurementReportCallback(
|
||||
NS_FATAL_ERROR("Invalid cell ID " << cellId);
|
||||
}
|
||||
|
||||
if (isCorrectMeasId)
|
||||
if (!isCorrectMeasId)
|
||||
{
|
||||
// verifying the report completeness
|
||||
LteRrcSap::MeasResults measResults = report.measResults;
|
||||
NS_LOG_DEBUG(
|
||||
this << " Serving cellId=" << cellId
|
||||
<< " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
|
||||
<< " dBm)"
|
||||
<< " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
|
||||
<< " dB)");
|
||||
return;
|
||||
}
|
||||
|
||||
// verifying reported best cells
|
||||
if (measResults.measResultListEutra.empty())
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
false,
|
||||
"Unexpected report content");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
true,
|
||||
"Unexpected report content");
|
||||
auto it = measResults.measResultListEutra.begin();
|
||||
NS_ASSERT(it != measResults.measResultListEutra.end());
|
||||
NS_ASSERT(it->physCellId != cellId);
|
||||
NS_ASSERT(it->physCellId <= 2);
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveCgiInfo,
|
||||
false,
|
||||
"Report contains cgi-info, which is not supported");
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveRsrpResult,
|
||||
true,
|
||||
"Report does not contain measured RSRP result");
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveRsrqResult,
|
||||
true,
|
||||
"Report does not contain measured RSRQ result");
|
||||
NS_LOG_DEBUG(this << " Neighbour cellId=" << it->physCellId
|
||||
<< " rsrp=" << (uint16_t)it->rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(it->rsrpResult) << " dBm)"
|
||||
<< " rsrq=" << (uint16_t)it->rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(it->rsrqResult) << " dB)");
|
||||
// verifying the report completeness
|
||||
LteRrcSap::MeasResults measResults = report.measResults;
|
||||
NS_LOG_DEBUG(
|
||||
this << " Serving cellId=" << cellId
|
||||
<< " rsrp=" << (uint16_t)measResults.measResultPCell.rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(measResults.measResultPCell.rsrpResult)
|
||||
<< " dBm)"
|
||||
<< " rsrq=" << (uint16_t)measResults.measResultPCell.rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(measResults.measResultPCell.rsrqResult)
|
||||
<< " dB)");
|
||||
|
||||
} // end of else of if (measResults.measResultListEutra.size () == 0)
|
||||
|
||||
// verifying the report timing
|
||||
bool hasEnded = m_itExpectedTime == m_expectedTime.end();
|
||||
NS_TEST_ASSERT_MSG_EQ(hasEnded,
|
||||
// verifying reported best cells
|
||||
if (measResults.measResultListEutra.empty())
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
false,
|
||||
"Reporting should not have occurred at "
|
||||
<< Simulator::Now().As(Time::S));
|
||||
if (!hasEnded)
|
||||
{
|
||||
hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
|
||||
NS_ASSERT(!hasEnded);
|
||||
"Unexpected report content");
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_TEST_ASSERT_MSG_EQ(measResults.haveMeasResultNeighCells,
|
||||
true,
|
||||
"Unexpected report content");
|
||||
auto it = measResults.measResultListEutra.begin();
|
||||
NS_ASSERT(it != measResults.measResultListEutra.end());
|
||||
NS_ASSERT(it->physCellId != cellId);
|
||||
NS_ASSERT(it->physCellId <= 2);
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveCgiInfo,
|
||||
false,
|
||||
"Report contains cgi-info, which is not supported");
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveRsrpResult,
|
||||
true,
|
||||
"Report does not contain measured RSRP result");
|
||||
NS_TEST_ASSERT_MSG_EQ(it->haveRsrqResult,
|
||||
true,
|
||||
"Report does not contain measured RSRQ result");
|
||||
NS_LOG_DEBUG(this << " Neighbour cellId=" << it->physCellId
|
||||
<< " rsrp=" << (uint16_t)it->rsrpResult << " ("
|
||||
<< EutranMeasurementMapping::RsrpRange2Dbm(it->rsrpResult) << " dBm)"
|
||||
<< " rsrq=" << (uint16_t)it->rsrqResult << " ("
|
||||
<< EutranMeasurementMapping::RsrqRange2Db(it->rsrqResult) << " dB)");
|
||||
|
||||
// using milliseconds to avoid floating-point comparison
|
||||
uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
|
||||
uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
|
||||
m_itExpectedTime++;
|
||||
} // end of else of if (measResults.measResultListEutra.size () == 0)
|
||||
|
||||
uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
|
||||
uint16_t referenceRsrp = *m_itExpectedRsrp;
|
||||
m_itExpectedRsrp++;
|
||||
// verifying the report timing
|
||||
bool hasEnded = m_itExpectedTime == m_expectedTime.end();
|
||||
NS_TEST_ASSERT_MSG_EQ(hasEnded,
|
||||
false,
|
||||
"Reporting should not have occurred at " << Simulator::Now().As(Time::S));
|
||||
if (hasEnded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ(timeNowMs,
|
||||
timeExpectedMs,
|
||||
"Reporting should not have occurred at this time");
|
||||
NS_TEST_ASSERT_MSG_EQ(observedRsrp,
|
||||
referenceRsrp,
|
||||
"The RSRP observed differs with the reference RSRP");
|
||||
hasEnded = m_itExpectedRsrp == m_expectedRsrp.end();
|
||||
NS_ASSERT(!hasEnded);
|
||||
|
||||
} // end of if (!hasEnded)
|
||||
// using milliseconds to avoid floating-point comparison
|
||||
uint64_t timeNowMs = Simulator::Now().GetMilliSeconds();
|
||||
uint64_t timeExpectedMs = m_itExpectedTime->GetMilliSeconds();
|
||||
m_itExpectedTime++;
|
||||
|
||||
} // end of if (report.measResults.measId == correctMeasId)
|
||||
uint16_t observedRsrp = measResults.measResultPCell.rsrpResult;
|
||||
uint16_t referenceRsrp = *m_itExpectedRsrp;
|
||||
m_itExpectedRsrp++;
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ(timeNowMs,
|
||||
timeExpectedMs,
|
||||
"Reporting should not have occurred at this time");
|
||||
NS_TEST_ASSERT_MSG_EQ(observedRsrp,
|
||||
referenceRsrp,
|
||||
"The RSRP observed differs with the reference RSRP");
|
||||
|
||||
} // end of void LteUeMeasurementsHandoverTestCase::RecvMeasurementReportCallback
|
||||
|
||||
Reference in New Issue
Block a user