Files
eden-sim/contrib/ethernet/model/switch-net-device.cc

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