405 lines
11 KiB
C++
405 lines
11 KiB
C++
/*
|
|
* Copyright (c) 2006 Georgia Tech Research Corporation, INRIA
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation;
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* Authors: George F. Riley<riley@ece.gatech.edu>
|
|
* Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
|
*/
|
|
|
|
#include "node.h"
|
|
|
|
#include "application.h"
|
|
#include "net-device.h"
|
|
#include "node-list.h"
|
|
|
|
#include "ns3/assert.h"
|
|
#include "ns3/boolean.h"
|
|
#include "ns3/global-value.h"
|
|
#include "ns3/log.h"
|
|
#include "ns3/object-vector.h"
|
|
#include "ns3/packet.h"
|
|
#include "ns3/simulator.h"
|
|
#include "ns3/uinteger.h"
|
|
|
|
namespace ns3
|
|
{
|
|
|
|
NS_LOG_COMPONENT_DEFINE("Node");
|
|
|
|
NS_OBJECT_ENSURE_REGISTERED(Node);
|
|
|
|
/**
|
|
* \relates Node
|
|
* \anchor GlobalValueChecksumEnabled
|
|
* \brief A global switch to enable all checksums for all protocols.
|
|
*/
|
|
static GlobalValue g_checksumEnabled =
|
|
GlobalValue("ChecksumEnabled",
|
|
"A global switch to enable all checksums for all protocols",
|
|
BooleanValue(false),
|
|
MakeBooleanChecker());
|
|
|
|
TypeId
|
|
Node::GetTypeId()
|
|
{
|
|
static TypeId tid =
|
|
TypeId("ns3::Node")
|
|
.SetParent<Object>()
|
|
.SetGroupName("Network")
|
|
.AddConstructor<Node>()
|
|
.AddAttribute("DeviceList",
|
|
"The list of devices associated to this Node.",
|
|
ObjectVectorValue(),
|
|
MakeObjectVectorAccessor(&Node::m_devices),
|
|
MakeObjectVectorChecker<NetDevice>())
|
|
.AddAttribute("ApplicationList",
|
|
"The list of applications associated to this Node.",
|
|
ObjectVectorValue(),
|
|
MakeObjectVectorAccessor(&Node::m_applications),
|
|
MakeObjectVectorChecker<Application>())
|
|
.AddAttribute("Id",
|
|
"The id (unique integer) of this Node.",
|
|
TypeId::ATTR_GET, // allow only getting it.
|
|
UintegerValue(0),
|
|
MakeUintegerAccessor(&Node::m_id),
|
|
MakeUintegerChecker<uint32_t>())
|
|
.AddAttribute(
|
|
"SystemId",
|
|
"The systemId of this node: a unique integer used for parallel simulations.",
|
|
TypeId::ATTR_GET | TypeId::ATTR_SET,
|
|
UintegerValue(0),
|
|
MakeUintegerAccessor(&Node::m_sid),
|
|
MakeUintegerChecker<uint32_t>());
|
|
return tid;
|
|
}
|
|
|
|
Node::Node()
|
|
: m_id(0),
|
|
m_sid(0)
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
Construct();
|
|
}
|
|
|
|
Node::Node(uint32_t sid)
|
|
: m_id(0),
|
|
m_sid(sid)
|
|
{
|
|
NS_LOG_FUNCTION(this << sid);
|
|
Construct();
|
|
}
|
|
|
|
void
|
|
Node::Construct()
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
m_id = NodeList::Add(this);
|
|
}
|
|
|
|
Node::~Node()
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
}
|
|
|
|
uint32_t
|
|
Node::GetId() const
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
return m_id;
|
|
}
|
|
|
|
Time
|
|
Node::GetLocalTime() const
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
return Simulator::Now();
|
|
}
|
|
|
|
uint32_t
|
|
Node::GetSystemId() const
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
return m_sid;
|
|
}
|
|
|
|
uint32_t
|
|
Node::AddDevice(Ptr<NetDevice> device)
|
|
{
|
|
NS_LOG_FUNCTION(this << device);
|
|
uint32_t index = m_devices.size();
|
|
m_devices.push_back(device);
|
|
device->SetNode(this);
|
|
device->SetIfIndex(index);
|
|
device->SetReceiveCallback(MakeCallback(&Node::NonPromiscReceiveFromDevice, this));
|
|
Simulator::ScheduleWithContext(GetId(), Seconds(0.0), &NetDevice::Initialize, device);
|
|
NotifyDeviceAdded(device);
|
|
return index;
|
|
}
|
|
|
|
Ptr<NetDevice>
|
|
Node::GetDevice(uint32_t index) const
|
|
{
|
|
NS_LOG_FUNCTION(this << index);
|
|
NS_ASSERT_MSG(index < m_devices.size(),
|
|
"Device index " << index << " is out of range (only have " << m_devices.size()
|
|
<< " devices).");
|
|
return m_devices[index];
|
|
}
|
|
|
|
uint32_t
|
|
Node::GetNDevices() const
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
return m_devices.size();
|
|
}
|
|
|
|
uint32_t
|
|
Node::AddApplication(Ptr<Application> application)
|
|
{
|
|
NS_LOG_FUNCTION(this << application);
|
|
uint32_t index = m_applications.size();
|
|
m_applications.push_back(application);
|
|
application->SetNode(this);
|
|
Simulator::ScheduleWithContext(GetId(), Seconds(0.0), &Application::Initialize, application);
|
|
return index;
|
|
}
|
|
|
|
Ptr<Application>
|
|
Node::GetApplication(uint32_t index) const
|
|
{
|
|
NS_LOG_FUNCTION(this << index);
|
|
NS_ASSERT_MSG(index < m_applications.size(),
|
|
"Application index " << index << " is out of range (only have "
|
|
<< m_applications.size() << " applications).");
|
|
return m_applications[index];
|
|
}
|
|
|
|
uint32_t
|
|
Node::GetNApplications() const
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
return m_applications.size();
|
|
}
|
|
|
|
void
|
|
Node::DoDispose()
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
m_deviceAdditionListeners.clear();
|
|
m_handlers.clear();
|
|
for (std::vector<Ptr<NetDevice>>::iterator i = m_devices.begin(); i != m_devices.end(); i++)
|
|
{
|
|
Ptr<NetDevice> device = *i;
|
|
device->Dispose();
|
|
*i = nullptr;
|
|
}
|
|
m_devices.clear();
|
|
for (std::vector<Ptr<Application>>::iterator i = m_applications.begin();
|
|
i != m_applications.end();
|
|
i++)
|
|
{
|
|
Ptr<Application> application = *i;
|
|
application->Dispose();
|
|
*i = nullptr;
|
|
}
|
|
m_applications.clear();
|
|
Object::DoDispose();
|
|
}
|
|
|
|
void
|
|
Node::DoInitialize()
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
for (std::vector<Ptr<NetDevice>>::iterator i = m_devices.begin(); i != m_devices.end(); i++)
|
|
{
|
|
Ptr<NetDevice> device = *i;
|
|
device->Initialize();
|
|
}
|
|
for (std::vector<Ptr<Application>>::iterator i = m_applications.begin();
|
|
i != m_applications.end();
|
|
i++)
|
|
{
|
|
Ptr<Application> application = *i;
|
|
application->Initialize();
|
|
}
|
|
|
|
Object::DoInitialize();
|
|
}
|
|
|
|
void
|
|
Node::RegisterProtocolHandler(ProtocolHandler handler,
|
|
uint16_t protocolType,
|
|
Ptr<NetDevice> device,
|
|
bool promiscuous)
|
|
{
|
|
NS_LOG_FUNCTION(this << &handler << protocolType << device << promiscuous);
|
|
struct Node::ProtocolHandlerEntry entry;
|
|
entry.handler = handler;
|
|
entry.protocol = protocolType;
|
|
entry.device = device;
|
|
entry.promiscuous = promiscuous;
|
|
|
|
// On demand enable promiscuous mode in netdevices
|
|
if (promiscuous)
|
|
{
|
|
if (!device)
|
|
{
|
|
for (std::vector<Ptr<NetDevice>>::iterator i = m_devices.begin(); i != m_devices.end();
|
|
i++)
|
|
{
|
|
Ptr<NetDevice> dev = *i;
|
|
dev->SetPromiscReceiveCallback(MakeCallback(&Node::PromiscReceiveFromDevice, this));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
device->SetPromiscReceiveCallback(MakeCallback(&Node::PromiscReceiveFromDevice, this));
|
|
}
|
|
}
|
|
|
|
m_handlers.push_back(entry);
|
|
}
|
|
|
|
void
|
|
Node::UnregisterProtocolHandler(ProtocolHandler handler)
|
|
{
|
|
NS_LOG_FUNCTION(this << &handler);
|
|
for (ProtocolHandlerList::iterator i = m_handlers.begin(); i != m_handlers.end(); i++)
|
|
{
|
|
if (i->handler.IsEqual(handler))
|
|
{
|
|
m_handlers.erase(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
Node::ChecksumEnabled()
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
BooleanValue val;
|
|
g_checksumEnabled.GetValue(val);
|
|
return val.Get();
|
|
}
|
|
|
|
bool
|
|
Node::PromiscReceiveFromDevice(Ptr<NetDevice> device,
|
|
Ptr<const Packet> packet,
|
|
uint16_t protocol,
|
|
const Address& from,
|
|
const Address& to,
|
|
NetDevice::PacketType packetType)
|
|
{
|
|
NS_LOG_FUNCTION(this << device << packet << protocol << &from << &to << packetType);
|
|
return ReceiveFromDevice(device, packet, protocol, from, to, packetType, true);
|
|
}
|
|
|
|
bool
|
|
Node::NonPromiscReceiveFromDevice(Ptr<NetDevice> device,
|
|
Ptr<const Packet> packet,
|
|
uint16_t protocol,
|
|
const Address& from)
|
|
{
|
|
NS_LOG_FUNCTION(this << device << packet << protocol << &from);
|
|
return ReceiveFromDevice(device,
|
|
packet,
|
|
protocol,
|
|
from,
|
|
device->GetAddress(),
|
|
NetDevice::PacketType(0),
|
|
false);
|
|
}
|
|
|
|
bool
|
|
Node::ReceiveFromDevice(Ptr<NetDevice> device,
|
|
Ptr<const Packet> packet,
|
|
uint16_t protocol,
|
|
const Address& from,
|
|
const Address& to,
|
|
NetDevice::PacketType packetType,
|
|
bool promiscuous)
|
|
{
|
|
NS_LOG_FUNCTION(this << device << packet << protocol << &from << &to << packetType
|
|
<< promiscuous);
|
|
NS_ASSERT_MSG(Simulator::GetContext() == GetId(),
|
|
"Received packet with erroneous context ; "
|
|
<< "make sure the channels in use are correctly updating events context "
|
|
<< "when transferring events from one node to another.");
|
|
NS_LOG_DEBUG("Node " << GetId() << " ReceiveFromDevice: dev " << device->GetIfIndex()
|
|
<< " (type=" << device->GetInstanceTypeId().GetName() << ") Packet UID "
|
|
<< packet->GetUid());
|
|
bool found = false;
|
|
|
|
for (ProtocolHandlerList::iterator i = m_handlers.begin(); i != m_handlers.end(); i++)
|
|
{
|
|
if (!i->device || (i->device == device))
|
|
{
|
|
if (i->protocol == 0 || i->protocol == protocol)
|
|
{
|
|
if (promiscuous == i->promiscuous)
|
|
{
|
|
i->handler(device, packet, protocol, from, to, packetType);
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
|
|
void
|
|
Node::RegisterDeviceAdditionListener(DeviceAdditionListener listener)
|
|
{
|
|
NS_LOG_FUNCTION(this << &listener);
|
|
m_deviceAdditionListeners.push_back(listener);
|
|
// and, then, notify the new listener about all existing devices.
|
|
for (std::vector<Ptr<NetDevice>>::const_iterator i = m_devices.begin(); i != m_devices.end();
|
|
++i)
|
|
{
|
|
listener(*i);
|
|
}
|
|
}
|
|
|
|
void
|
|
Node::UnregisterDeviceAdditionListener(DeviceAdditionListener listener)
|
|
{
|
|
NS_LOG_FUNCTION(this << &listener);
|
|
for (DeviceAdditionListenerList::iterator i = m_deviceAdditionListeners.begin();
|
|
i != m_deviceAdditionListeners.end();
|
|
i++)
|
|
{
|
|
if ((*i).IsEqual(listener))
|
|
{
|
|
m_deviceAdditionListeners.erase(i);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
Node::NotifyDeviceAdded(Ptr<NetDevice> device)
|
|
{
|
|
NS_LOG_FUNCTION(this << device);
|
|
for (DeviceAdditionListenerList::iterator i = m_deviceAdditionListeners.begin();
|
|
i != m_deviceAdditionListeners.end();
|
|
i++)
|
|
{
|
|
(*i)(device);
|
|
}
|
|
}
|
|
|
|
} // namespace ns3
|