428 lines
12 KiB
C++
428 lines
12 KiB
C++
#include "switch-net-device.h"
|
|
|
|
#include "ns3/boolean.h"
|
|
#include "ns3/channel.h"
|
|
#include "ns3/log.h"
|
|
#include "ns3/node.h"
|
|
#include "ns3/packet.h"
|
|
#include "ns3/uinteger.h"
|
|
#include "ns3/names.h"
|
|
#include "ns3/random-variable-stream.h"
|
|
|
|
#include "ns3/ethernet-header2.h"
|
|
#include "ns3/net-device.h"
|
|
|
|
|
|
/**
|
|
* \file
|
|
* \ingroup ethernet
|
|
* ns3::SwitchNetDevice implementation.
|
|
*/
|
|
|
|
namespace ns3
|
|
{
|
|
|
|
NS_LOG_COMPONENT_DEFINE("SwitchNetDevice");
|
|
|
|
NS_OBJECT_ENSURE_REGISTERED(SwitchNetDevice);
|
|
|
|
TypeId
|
|
SwitchNetDevice::GetTypeId()
|
|
{
|
|
static TypeId tid =
|
|
TypeId("ns3::SwitchNetDevice")
|
|
.SetParent<NetDevice>()
|
|
.SetGroupName("Ethernet")
|
|
.AddConstructor<SwitchNetDevice>()
|
|
.AddAttribute("Mtu",
|
|
"The MAC-level Maximum Transmission Unit",
|
|
UintegerValue(1500),
|
|
MakeUintegerAccessor(&SwitchNetDevice::SetMtu, &SwitchNetDevice::GetMtu),
|
|
MakeUintegerChecker<uint16_t>())
|
|
.AddAttribute("MinForwardingLatency",
|
|
"The minimum latency experienced by the packet during forwarding",
|
|
TimeValue(Seconds(0)),
|
|
MakeTimeAccessor(&SwitchNetDevice::m_minForwardingLatency),
|
|
MakeTimeChecker())
|
|
.AddAttribute("MaxForwardingLatency",
|
|
"The maximun latency experienced by the packet during forwarding",
|
|
TimeValue(Seconds(0)),
|
|
MakeTimeAccessor(&SwitchNetDevice::m_maxForwardingLatency),
|
|
MakeTimeChecker())
|
|
.AddAttribute("MaxPortNumber",
|
|
"The maximum number of port",
|
|
UintegerValue(65535),
|
|
MakeUintegerAccessor(&SwitchNetDevice::m_maxPortNumber),
|
|
MakeUintegerChecker<uint16_t>())
|
|
.AddAttribute("MaxFdbEntryNumber",
|
|
"The maximum number of entry in the forwarding database",
|
|
UintegerValue(65535),
|
|
MakeUintegerAccessor(&SwitchNetDevice::m_maxFdbEntryNumber),
|
|
MakeUintegerChecker<uint16_t>());
|
|
return tid;
|
|
}
|
|
|
|
SwitchNetDevice::SwitchNetDevice()
|
|
: m_node(nullptr),
|
|
m_ifIndex(0)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
m_channel = CreateObject<SwitchChannel>();
|
|
}
|
|
|
|
SwitchNetDevice::~SwitchNetDevice()
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::DoDispose()
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
for (auto iter = m_ports.begin(); iter != m_ports.end(); iter++)
|
|
{
|
|
*iter = nullptr;
|
|
}
|
|
m_ports.clear();
|
|
m_forwardingTable.clear();
|
|
m_channel = nullptr;
|
|
m_node = nullptr;
|
|
NetDevice::DoDispose();
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::ReceiveFromDevice(Ptr<NetDevice> incomingPort,
|
|
Ptr<const Packet> packet,
|
|
uint16_t protocol,
|
|
const Address& src,
|
|
const Address& dst,
|
|
PacketType packetType)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
NS_LOG_DEBUG("UID is " << packet->GetUid());
|
|
|
|
Mac48Address src48 = Mac48Address::ConvertFrom(src);
|
|
Mac48Address dst48 = Mac48Address::ConvertFrom(dst);
|
|
|
|
if (!m_promiscRxCallback.IsNull())
|
|
{
|
|
m_promiscRxCallback(this, packet, protocol, src, dst, packetType);
|
|
}
|
|
switch (packetType)
|
|
{
|
|
case PACKET_HOST:
|
|
if (dst48 == m_address)
|
|
{
|
|
m_rxCallback(this, packet, protocol, src);
|
|
}
|
|
break;
|
|
case PACKET_MULTICAST:
|
|
case PACKET_BROADCAST:
|
|
m_rxCallback(this, packet, protocol, src);
|
|
ForwardBroadcast(incomingPort, packet, protocol, src48, dst48);
|
|
break;
|
|
|
|
case PACKET_OTHERHOST:
|
|
if (dst48 == m_address)
|
|
{
|
|
m_rxCallback(this, packet, protocol, src);
|
|
}
|
|
else
|
|
{
|
|
Forward(incomingPort, packet, protocol, src48, dst48);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::Forward(Ptr<NetDevice> incomingPort,
|
|
Ptr<const Packet> packet,
|
|
uint16_t protocol,
|
|
Mac48Address src,
|
|
Mac48Address dst)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
Ptr<Packet> originalPacket = packet->Copy();
|
|
EthernetHeader2 header;
|
|
originalPacket->RemoveHeader(header);
|
|
uint16_t vid = header.GetVid();
|
|
//NS_LOG_INFO(Names::FindName(this) << " Look in forwarding table for Pkt #" << packet->GetUid());
|
|
std::vector<Ptr<NetDevice>> outPorts = GetOutputPortsFromForwardingTable(dst, vid);
|
|
EventId e;
|
|
int s = outPorts.size();
|
|
for(int i=0; i < s; i++){
|
|
//Avoid sending on the incomingPort
|
|
if(outPorts[i] != incomingPort){
|
|
Ptr<UniformRandomVariable> randVar = CreateObject<UniformRandomVariable>();
|
|
Time forwardingLatency = NanoSeconds(randVar->GetValue(m_minForwardingLatency.GetNanoSeconds(), m_maxForwardingLatency.GetNanoSeconds()));
|
|
Simulator::Schedule(forwardingLatency, &NetDevice::SendFrom, outPorts[i], packet->Copy(), src, dst, protocol);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::ForwardBroadcast(Ptr<NetDevice> incomingPort,
|
|
Ptr<const Packet> packet,
|
|
uint16_t protocol,
|
|
Mac48Address src,
|
|
Mac48Address dst)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
|
|
Forward(incomingPort, packet, protocol, src, dst);
|
|
}
|
|
|
|
std::vector<Ptr<NetDevice>>
|
|
SwitchNetDevice::GetOutputPortsFromForwardingTable(Mac48Address dest, uint16_t vid)
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
int s = m_forwardingTable.size();
|
|
for(int i=0; i < s; i++){
|
|
if(m_forwardingTable[i].dest == dest and m_forwardingTable[i].vid==vid){
|
|
// NS_LOG_INFO(Names::FindName(this) << " Forwarding Table : Match on vid "<< vid << " for " << m_forwardingTable[i].associatedPorts.size() << " output port(s) ");
|
|
return m_forwardingTable[i].associatedPorts;
|
|
}
|
|
}
|
|
// NS_LOG_INFO(Names::FindName(this) << " Forwarding Table : No Match on vid "<< vid);
|
|
return {};
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::AddForwardingTableEntry(Mac48Address dest, uint16_t vid, std::vector<Ptr<NetDevice>> outPorts)
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
NS_ASSERT_MSG(m_forwardingTable.size() < m_maxFdbEntryNumber, "Trying to add more forwarding database entry than the " << m_maxFdbEntryNumber << " available.");
|
|
PortsToVidAssociation entry = {dest, vid, outPorts};
|
|
m_forwardingTable.insert(m_forwardingTable.end(), entry);
|
|
}
|
|
|
|
uint32_t
|
|
SwitchNetDevice::GetNSwitchPorts() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return m_ports.size();
|
|
}
|
|
|
|
Ptr<NetDevice>
|
|
SwitchNetDevice::GetSwitchPort(uint32_t n) const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return m_ports[n];
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::AddSwitchPort(Ptr<NetDevice> switchPort)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
NS_ASSERT_MSG(m_ports.size() < m_maxPortNumber, "Trying to add more switch port than the " << m_maxPortNumber << " available.");
|
|
//NS_ASSERT(switchPort != this);
|
|
if (!Mac48Address::IsMatchingType(switchPort->GetAddress()))
|
|
{
|
|
NS_FATAL_ERROR("Device does not support eui 48 addresses: cannot be added to switch.");
|
|
}
|
|
if (!switchPort->SupportsSendFrom())
|
|
{
|
|
NS_FATAL_ERROR("Device does not support SendFrom: cannot be added to switch.");
|
|
}
|
|
if (m_address == Mac48Address())
|
|
{
|
|
m_address = Mac48Address::ConvertFrom(switchPort->GetAddress());
|
|
}
|
|
|
|
NS_LOG_DEBUG("RegisterProtocolHandler for " << switchPort->GetInstanceTypeId().GetName());
|
|
m_node->RegisterProtocolHandler(MakeCallback(&SwitchNetDevice::ReceiveFromDevice, this),
|
|
0,
|
|
switchPort,
|
|
true);
|
|
m_ports.push_back(switchPort);
|
|
m_channel->AddChannel(switchPort->GetChannel());
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::SetIfIndex(const uint32_t index)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
m_ifIndex = index;
|
|
}
|
|
|
|
uint32_t
|
|
SwitchNetDevice::GetIfIndex() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return m_ifIndex;
|
|
}
|
|
|
|
Ptr<Channel>
|
|
SwitchNetDevice::GetChannel() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return m_channel;
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::SetAddress(Address address)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
m_address = Mac48Address::ConvertFrom(address);
|
|
}
|
|
|
|
Address
|
|
SwitchNetDevice::GetAddress() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return m_address;
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::SetMtu(const uint16_t mtu)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
m_mtu = mtu;
|
|
return true;
|
|
}
|
|
|
|
uint16_t
|
|
SwitchNetDevice::GetMtu() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return m_mtu;
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::IsLinkUp() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return true;
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::AddLinkChangeCallback(Callback<void> callback)
|
|
{
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::IsBroadcast() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return true;
|
|
}
|
|
|
|
Address
|
|
SwitchNetDevice::GetBroadcast() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return Mac48Address("ff:ff:ff:ff:ff:ff");
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::IsMulticast() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return true;
|
|
}
|
|
|
|
Address
|
|
SwitchNetDevice::GetMulticast(Ipv4Address multicastGroup) const
|
|
{
|
|
NS_LOG_FUNCTION(this << multicastGroup);
|
|
Mac48Address multicast = Mac48Address::GetMulticast(multicastGroup);
|
|
return multicast;
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::IsPointToPoint() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::IsBridge() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return SendFrom(packet, m_address, dest, protocolNumber);
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::SendFrom(Ptr<Packet> packet,
|
|
const Address& source,
|
|
const Address& dest,
|
|
uint16_t protocolNumber)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
Mac48Address src = Mac48Address::ConvertFrom(source);
|
|
Mac48Address dst = Mac48Address::ConvertFrom(dest);
|
|
|
|
|
|
Ptr<Packet> originalPacket = packet->Copy();
|
|
EthernetHeader2 header;
|
|
originalPacket->RemoveHeader(header);
|
|
uint16_t vid = header.GetVid();
|
|
|
|
std::vector<Ptr<NetDevice>> outPorts = GetOutputPortsFromForwardingTable(dst, vid);
|
|
int s = outPorts.size();
|
|
for(int i=0; i < s; i++){
|
|
outPorts[i]->SendFrom(packet->Copy(), src, dst, protocolNumber);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Ptr<Node>
|
|
SwitchNetDevice::GetNode() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return m_node;
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::SetNode(Ptr<Node> node)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
m_node = node;
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::NeedsArp() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return true;
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
m_rxCallback = cb;
|
|
}
|
|
|
|
void
|
|
SwitchNetDevice::SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
m_promiscRxCallback = cb;
|
|
}
|
|
|
|
bool
|
|
SwitchNetDevice::SupportsSendFrom() const
|
|
{
|
|
NS_LOG_FUNCTION_NOARGS();
|
|
return true;
|
|
}
|
|
|
|
Address
|
|
SwitchNetDevice::GetMulticast(Ipv6Address addr) const
|
|
{
|
|
NS_LOG_FUNCTION(this << addr);
|
|
return Mac48Address::GetMulticast(addr);
|
|
}
|
|
|
|
} // namespace ns3
|