internet: (fixes #910) Release memory when sockets are closed
This commit is contained in:
@@ -42,12 +42,13 @@
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/object-vector.h"
|
||||
#include "ns3/object-map.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/simulator.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace ns3
|
||||
@@ -72,30 +73,33 @@ const uint8_t TcpL4Protocol::PROT_NUMBER = 6;
|
||||
TypeId
|
||||
TcpL4Protocol::GetTypeId()
|
||||
{
|
||||
static TypeId tid = TypeId("ns3::TcpL4Protocol")
|
||||
.SetParent<IpL4Protocol>()
|
||||
.SetGroupName("Internet")
|
||||
.AddConstructor<TcpL4Protocol>()
|
||||
.AddAttribute("RttEstimatorType",
|
||||
"Type of RttEstimator objects.",
|
||||
TypeIdValue(RttMeanDeviation::GetTypeId()),
|
||||
MakeTypeIdAccessor(&TcpL4Protocol::m_rttTypeId),
|
||||
MakeTypeIdChecker())
|
||||
.AddAttribute("SocketType",
|
||||
"Socket type of TCP objects.",
|
||||
TypeIdValue(TcpCubic::GetTypeId()),
|
||||
MakeTypeIdAccessor(&TcpL4Protocol::m_congestionTypeId),
|
||||
MakeTypeIdChecker())
|
||||
.AddAttribute("RecoveryType",
|
||||
"Recovery type of TCP objects.",
|
||||
TypeIdValue(TcpPrrRecovery::GetTypeId()),
|
||||
MakeTypeIdAccessor(&TcpL4Protocol::m_recoveryTypeId),
|
||||
MakeTypeIdChecker())
|
||||
.AddAttribute("SocketList",
|
||||
"The list of sockets associated to this protocol.",
|
||||
ObjectVectorValue(),
|
||||
MakeObjectVectorAccessor(&TcpL4Protocol::m_sockets),
|
||||
MakeObjectVectorChecker<TcpSocketBase>());
|
||||
static TypeId tid =
|
||||
TypeId("ns3::TcpL4Protocol")
|
||||
.SetParent<IpL4Protocol>()
|
||||
.SetGroupName("Internet")
|
||||
.AddConstructor<TcpL4Protocol>()
|
||||
.AddAttribute("RttEstimatorType",
|
||||
"Type of RttEstimator objects.",
|
||||
TypeIdValue(RttMeanDeviation::GetTypeId()),
|
||||
MakeTypeIdAccessor(&TcpL4Protocol::m_rttTypeId),
|
||||
MakeTypeIdChecker())
|
||||
.AddAttribute("SocketType",
|
||||
"Socket type of TCP objects.",
|
||||
TypeIdValue(TcpCubic::GetTypeId()),
|
||||
MakeTypeIdAccessor(&TcpL4Protocol::m_congestionTypeId),
|
||||
MakeTypeIdChecker())
|
||||
.AddAttribute("RecoveryType",
|
||||
"Recovery type of TCP objects.",
|
||||
TypeIdValue(TcpPrrRecovery::GetTypeId()),
|
||||
MakeTypeIdAccessor(&TcpL4Protocol::m_recoveryTypeId),
|
||||
MakeTypeIdChecker())
|
||||
.AddAttribute("SocketList",
|
||||
"A container of sockets associated to this protocol. "
|
||||
"The underlying type is an unordered map, the attribute name "
|
||||
"is kept for backward compatibility.",
|
||||
ObjectMapValue(),
|
||||
MakeObjectMapAccessor(&TcpL4Protocol::m_sockets),
|
||||
MakeObjectMapChecker<TcpSocketBase>());
|
||||
return tid;
|
||||
}
|
||||
|
||||
@@ -213,7 +217,7 @@ TcpL4Protocol::CreateSocket(TypeId congestionTypeId, TypeId recoveryTypeId)
|
||||
socket->SetCongestionControlAlgorithm(algo);
|
||||
socket->SetRecoveryAlgorithm(recovery);
|
||||
|
||||
m_sockets.push_back(socket);
|
||||
m_sockets[m_socketIndex++] = socket;
|
||||
return socket;
|
||||
}
|
||||
|
||||
@@ -747,36 +751,30 @@ void
|
||||
TcpL4Protocol::AddSocket(Ptr<TcpSocketBase> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << socket);
|
||||
std::vector<Ptr<TcpSocketBase>>::iterator it = m_sockets.begin();
|
||||
|
||||
while (it != m_sockets.end())
|
||||
for (auto& socketItem : m_sockets)
|
||||
{
|
||||
if (*it == socket)
|
||||
if (socketItem.second == socket)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
m_sockets.push_back(socket);
|
||||
m_sockets[m_socketIndex++] = socket;
|
||||
}
|
||||
|
||||
bool
|
||||
TcpL4Protocol::RemoveSocket(Ptr<TcpSocketBase> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << socket);
|
||||
std::vector<Ptr<TcpSocketBase>>::iterator it = m_sockets.begin();
|
||||
|
||||
while (it != m_sockets.end())
|
||||
for (auto& socketItem : m_sockets)
|
||||
{
|
||||
if (*it == socket)
|
||||
if (socketItem.second == socket)
|
||||
{
|
||||
m_sockets.erase(it);
|
||||
socketItem.second = nullptr;
|
||||
m_sockets.erase(socketItem.first);
|
||||
return true;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "ns3/sequence-number.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
@@ -334,13 +335,15 @@ class TcpL4Protocol : public IpL4Protocol
|
||||
const Address& incomingDAddr);
|
||||
|
||||
private:
|
||||
Ptr<Node> m_node; //!< the node this stack is associated with
|
||||
Ipv4EndPointDemux* m_endPoints; //!< A list of IPv4 end points.
|
||||
Ipv6EndPointDemux* m_endPoints6; //!< A list of IPv6 end points.
|
||||
TypeId m_rttTypeId; //!< The RTT Estimator TypeId
|
||||
TypeId m_congestionTypeId; //!< The socket TypeId
|
||||
TypeId m_recoveryTypeId; //!< The recovery TypeId
|
||||
std::vector<Ptr<TcpSocketBase>> m_sockets; //!< list of sockets
|
||||
Ptr<Node> m_node; //!< the node this stack is associated with
|
||||
Ipv4EndPointDemux* m_endPoints; //!< A list of IPv4 end points.
|
||||
Ipv6EndPointDemux* m_endPoints6; //!< A list of IPv6 end points.
|
||||
TypeId m_rttTypeId; //!< The RTT Estimator TypeId
|
||||
TypeId m_congestionTypeId; //!< The socket TypeId
|
||||
TypeId m_recoveryTypeId; //!< The recovery TypeId
|
||||
std::unordered_map<uint64_t, Ptr<TcpSocketBase>>
|
||||
m_sockets; //!< Unordered map of socket IDs and corresponding sockets
|
||||
uint64_t m_socketIndex{0}; //!< index of the next socket to be created
|
||||
IpL4Protocol::DownTargetCallback m_downTarget; //!< Callback to send packets over IPv4
|
||||
IpL4Protocol::DownTargetCallback6 m_downTarget6; //!< Callback to send packets over IPv6
|
||||
|
||||
|
||||
@@ -2875,6 +2875,11 @@ TcpSocketBase::SendRST()
|
||||
void
|
||||
TcpSocketBase::DeallocateEndPoint()
|
||||
{
|
||||
// note: it shouldn't be necessary to invalidate the callback and manually call
|
||||
// TcpL4Protocol::RemoveSocket. Alas, if one relies on the endpoint destruction
|
||||
// callback, there's a weird memory access to a free'd area. Harmless, but valgrind
|
||||
// considers it an error.
|
||||
|
||||
if (m_endPoint != nullptr)
|
||||
{
|
||||
CancelAllTimers();
|
||||
|
||||
@@ -35,9 +35,11 @@
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/object-vector.h"
|
||||
#include "ns3/object-map.h"
|
||||
#include "ns3/packet.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
@@ -51,15 +53,18 @@ const uint8_t UdpL4Protocol::PROT_NUMBER = 17;
|
||||
TypeId
|
||||
UdpL4Protocol::GetTypeId()
|
||||
{
|
||||
static TypeId tid = TypeId("ns3::UdpL4Protocol")
|
||||
.SetParent<IpL4Protocol>()
|
||||
.SetGroupName("Internet")
|
||||
.AddConstructor<UdpL4Protocol>()
|
||||
.AddAttribute("SocketList",
|
||||
"The list of sockets associated to this protocol.",
|
||||
ObjectVectorValue(),
|
||||
MakeObjectVectorAccessor(&UdpL4Protocol::m_sockets),
|
||||
MakeObjectVectorChecker<UdpSocketImpl>());
|
||||
static TypeId tid =
|
||||
TypeId("ns3::UdpL4Protocol")
|
||||
.SetParent<IpL4Protocol>()
|
||||
.SetGroupName("Internet")
|
||||
.AddConstructor<UdpL4Protocol>()
|
||||
.AddAttribute("SocketList",
|
||||
"A container of sockets associated to this protocol. "
|
||||
"The underlying type is an unordered map, the attribute name "
|
||||
"is kept for backward compatibility.",
|
||||
ObjectMapValue(),
|
||||
MakeObjectMapAccessor(&UdpL4Protocol::m_sockets),
|
||||
MakeObjectMapChecker<UdpSocketImpl>());
|
||||
return tid;
|
||||
}
|
||||
|
||||
@@ -133,9 +138,9 @@ void
|
||||
UdpL4Protocol::DoDispose()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
for (std::vector<Ptr<UdpSocketImpl>>::iterator i = m_sockets.begin(); i != m_sockets.end(); i++)
|
||||
for (auto i = m_sockets.begin(); i != m_sockets.end(); i++)
|
||||
{
|
||||
*i = nullptr;
|
||||
i->second = nullptr;
|
||||
}
|
||||
m_sockets.clear();
|
||||
|
||||
@@ -165,7 +170,7 @@ UdpL4Protocol::CreateSocket()
|
||||
Ptr<UdpSocketImpl> socket = CreateObject<UdpSocketImpl>();
|
||||
socket->SetNode(m_node);
|
||||
socket->SetUdp(this);
|
||||
m_sockets.push_back(socket);
|
||||
m_sockets[m_socketIndex++] = socket;
|
||||
return socket;
|
||||
}
|
||||
|
||||
@@ -545,4 +550,21 @@ UdpL4Protocol::GetDownTarget6() const
|
||||
return m_downTarget6;
|
||||
}
|
||||
|
||||
bool
|
||||
UdpL4Protocol::RemoveSocket(Ptr<UdpSocketImpl> socket)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << socket);
|
||||
|
||||
for (auto& socketItem : m_sockets)
|
||||
{
|
||||
if (socketItem.second == socket)
|
||||
{
|
||||
socketItem.second = nullptr;
|
||||
m_sockets.erase(socketItem.first);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ns3/ptr.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
@@ -183,6 +184,14 @@ class UdpL4Protocol : public IpL4Protocol
|
||||
*/
|
||||
void DeAllocate(Ipv6EndPoint* endPoint);
|
||||
|
||||
/**
|
||||
* \brief Remove a socket from the internal list
|
||||
*
|
||||
* \param socket socket to remove
|
||||
* \return true if the socket has been removed
|
||||
*/
|
||||
bool RemoveSocket(Ptr<UdpSocketImpl> socket);
|
||||
|
||||
// called by UdpSocket.
|
||||
/**
|
||||
* \brief Send a packet via UDP (IPv4)
|
||||
@@ -283,11 +292,13 @@ class UdpL4Protocol : public IpL4Protocol
|
||||
void NotifyNewAggregate() override;
|
||||
|
||||
private:
|
||||
Ptr<Node> m_node; //!< the node this stack is associated with
|
||||
Ptr<Node> m_node; //!< The node this stack is associated with
|
||||
Ipv4EndPointDemux* m_endPoints; //!< A list of IPv4 end points.
|
||||
Ipv6EndPointDemux* m_endPoints6; //!< A list of IPv6 end points.
|
||||
|
||||
std::vector<Ptr<UdpSocketImpl>> m_sockets; //!< list of sockets
|
||||
std::unordered_map<uint64_t, Ptr<UdpSocketImpl>>
|
||||
m_sockets; //!< Unordered map of socket IDs and corresponding sockets
|
||||
uint64_t m_socketIndex{0}; //!< Index of the next socket to be created
|
||||
IpL4Protocol::DownTargetCallback m_downTarget; //!< Callback to send packets over IPv4
|
||||
IpL4Protocol::DownTargetCallback6 m_downTarget6; //!< Callback to send packets over IPv6
|
||||
};
|
||||
|
||||
@@ -176,6 +176,10 @@ void
|
||||
UdpSocketImpl::Destroy()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
if (m_udp)
|
||||
{
|
||||
m_udp->RemoveSocket(this);
|
||||
}
|
||||
m_endPoint = nullptr;
|
||||
}
|
||||
|
||||
@@ -183,6 +187,10 @@ void
|
||||
UdpSocketImpl::Destroy6()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
if (m_udp)
|
||||
{
|
||||
m_udp->RemoveSocket(this);
|
||||
}
|
||||
m_endPoint6 = nullptr;
|
||||
}
|
||||
|
||||
@@ -192,13 +200,11 @@ UdpSocketImpl::DeallocateEndPoint()
|
||||
{
|
||||
if (m_endPoint != nullptr)
|
||||
{
|
||||
m_endPoint->SetDestroyCallback(MakeNullCallback<void>());
|
||||
m_udp->DeAllocate(m_endPoint);
|
||||
m_endPoint = nullptr;
|
||||
}
|
||||
if (m_endPoint6 != nullptr)
|
||||
{
|
||||
m_endPoint6->SetDestroyCallback(MakeNullCallback<void>());
|
||||
m_udp->DeAllocate(m_endPoint6);
|
||||
m_endPoint6 = nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user