Update README and add contrib dir
This commit is contained in:
769
contrib/ethernet/model/ethernet-net-device.cc
Normal file
769
contrib/ethernet/model/ethernet-net-device.cc
Normal file
@@ -0,0 +1,769 @@
|
||||
#include "ethernet-net-device.h"
|
||||
|
||||
#include "ethernet-channel.h"
|
||||
#include "ethernet-header2.h"
|
||||
|
||||
#include "ns3/error-model.h"
|
||||
#include "ns3/llc-snap-header.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/mac48-address.h"
|
||||
#include "ns3/pointer.h"
|
||||
#include "ns3/queue.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/ethernet-trailer.h"
|
||||
#include "ns3/timestamp-tag.h"
|
||||
#include "ns3/names.h"
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("EthernetNetDevice");
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED(EthernetNetDevice);
|
||||
|
||||
TypeId
|
||||
EthernetNetDevice::GetTypeId()
|
||||
{
|
||||
static TypeId tid =
|
||||
TypeId("ns3::EthernetNetDevice")
|
||||
.SetParent<NetDevice>()
|
||||
.SetGroupName("Ethernet")
|
||||
.AddConstructor<EthernetNetDevice>()
|
||||
.AddAttribute("Mtu",
|
||||
"The MAC-level Maximum Transmission Unit",
|
||||
UintegerValue(DEFAULT_MTU),
|
||||
MakeUintegerAccessor(&EthernetNetDevice::SetMtu,
|
||||
&EthernetNetDevice::GetMtu),
|
||||
MakeUintegerChecker<uint16_t>())
|
||||
.AddAttribute("Address",
|
||||
"The MAC address of this device.",
|
||||
Mac48AddressValue(Mac48Address("00:00:00:00:ED:E1")),
|
||||
MakeMac48AddressAccessor(&EthernetNetDevice::m_address),
|
||||
MakeMac48AddressChecker())
|
||||
.AddAttribute("DataRate",
|
||||
"The default data rate for point to point links",
|
||||
DataRateValue(DataRate("1Gb/s")),
|
||||
MakeDataRateAccessor(&EthernetNetDevice::m_bps),
|
||||
MakeDataRateChecker())
|
||||
.AddAttribute("ReceiveErrorModel",
|
||||
"The receiver error model used to simulate packet loss",
|
||||
PointerValue(),
|
||||
MakePointerAccessor(&EthernetNetDevice::m_receiveErrorModel),
|
||||
MakePointerChecker<ErrorModel>())
|
||||
.AddAttribute("preambleAndSFDGap",
|
||||
"Number of byte for the preamble and start of frame delimiter gap",
|
||||
UintegerValue(8),
|
||||
MakeUintegerAccessor(&EthernetNetDevice::m_preambleAndSFDGap),
|
||||
MakeUintegerChecker<uint8_t>())
|
||||
.AddAttribute("InterframeGap",
|
||||
"Number of byte for the interframe gap",
|
||||
UintegerValue(12),
|
||||
MakeUintegerAccessor(&EthernetNetDevice::m_interframeGap),
|
||||
MakeUintegerChecker<uint8_t>())
|
||||
|
||||
//
|
||||
// Trace sources at the "top" of the net device, where packets transition
|
||||
// to/from higher layers.
|
||||
//
|
||||
.AddTraceSource("MacTx",
|
||||
"Trace source indicating a packet has arrived "
|
||||
"for transmission by this device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_macTxTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("MacTxAnimation",
|
||||
"Trace source indicating a packet has arrived "
|
||||
"for transmission by this device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_macTxAnimationTrace),
|
||||
"ns3::EthernetNetDevice::MacTxAnimationCallback")
|
||||
.AddTraceSource("MacTxDrop",
|
||||
"Trace source indicating a packet has been dropped "
|
||||
"by the device before transmission",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_macTxDropTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("MacPromiscRx",
|
||||
"A packet has been received by this device, "
|
||||
"has been passed up from the physical layer "
|
||||
"and is being forwarded up the local protocol stack. "
|
||||
"This is a promiscuous trace,",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_macPromiscRxTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("MacRx",
|
||||
"A packet has been received by this device, "
|
||||
"has been passed up from the physical layer "
|
||||
"and is being forwarded up the local protocol stack. "
|
||||
"This is a non-promiscuous trace,",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_macRxTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("MacRxAnimation",
|
||||
"Trace source indicating a packet has arrived "
|
||||
"in this device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_macRxAnimationTrace),
|
||||
"ns3::EthernetNetDevice::MacRxAnimationCallback")
|
||||
#if 0
|
||||
// Not currently implemented for this device
|
||||
.AddTraceSource ("MacRxDrop",
|
||||
"Trace source indicating a packet was dropped "
|
||||
"before being forwarded up the stack",
|
||||
MakeTraceSourceAccessor (&EthernetNetDevice::m_macRxDropTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
#endif
|
||||
//
|
||||
// Trace sources at the "bottom" of the net device, where packets transition
|
||||
// to/from the channel.
|
||||
//
|
||||
.AddTraceSource("PhyTxBegin",
|
||||
"Trace source indicating a packet has begun "
|
||||
"transmitting over the channel",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_phyTxBeginTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("PhyTxEnd",
|
||||
"Trace source indicating a packet has been "
|
||||
"completely transmitted over the channel",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_phyTxEndTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("PhyTxDrop",
|
||||
"Trace source indicating a packet has been "
|
||||
"dropped by the device during transmission",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_phyTxDropTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("Latency",
|
||||
"Trace source to compute network latency ",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_latencyTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("FIFOState",
|
||||
"Trace source to study the FIFO state ",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_FIFOStateSnifferTrace),
|
||||
"ns3::EthernetNetDevice::m_FIFOStateSnifferTrace")
|
||||
#if 0
|
||||
// Not currently implemented for this device
|
||||
.AddTraceSource ("PhyRxBegin",
|
||||
"Trace source indicating a packet has begun "
|
||||
"being received by the device",
|
||||
MakeTraceSourceAccessor (&EthernetNetDevice::m_phyRxBeginTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
#endif
|
||||
.AddTraceSource("PhyRxEnd",
|
||||
"Trace source indicating a packet has been "
|
||||
"completely received by the device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_phyRxEndTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("PhyRxDrop",
|
||||
"Trace source indicating a packet has been "
|
||||
"dropped by the device during reception",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_phyRxDropTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
|
||||
//
|
||||
// Trace sources designed to simulate a packet sniffer facility (tcpdump).
|
||||
// Note that there is really no difference between promiscuous and
|
||||
// non-promiscuous traces in a point-to-point link.
|
||||
//
|
||||
.AddTraceSource("Sniffer",
|
||||
"Trace source simulating a non-promiscuous packet sniffer "
|
||||
"attached to the device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_snifferTrace),
|
||||
"ns3::Packet::TracedCallback")
|
||||
.AddTraceSource("PromiscSniffer",
|
||||
"Trace source simulating a promiscuous packet sniffer "
|
||||
"attached to the device",
|
||||
MakeTraceSourceAccessor(&EthernetNetDevice::m_promiscSnifferTrace),
|
||||
"ns3::Packet::TracedCallback");
|
||||
return tid;
|
||||
}
|
||||
|
||||
EthernetNetDevice::EthernetNetDevice()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_txMachineState = READY;
|
||||
m_channel = nullptr;
|
||||
m_linkUp = false;
|
||||
m_currentPkt = nullptr;
|
||||
}
|
||||
|
||||
EthernetNetDevice::~EthernetNetDevice()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::AddHeader(Ptr<Packet> p, Mac48Address dst, Mac48Address src, uint16_t ethertype)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
EthernetHeader2 ethHeader;
|
||||
ethHeader.SetDest(dst);
|
||||
ethHeader.SetSrc(src);
|
||||
ethHeader.SetEthertype(ethertype);
|
||||
p->AddHeader(ethHeader);
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::AddHeader(Ptr<Packet> p, Mac48Address dst, Mac48Address src, uint16_t ethertype, uint16_t vid, uint8_t pcp, uint8_t dei)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
EthernetHeader2 ethHeader;
|
||||
ethHeader.SetDest(dst);
|
||||
ethHeader.SetSrc(src);
|
||||
ethHeader.SetEthertype(ethertype);
|
||||
ethHeader.SetVlanTag(pcp, dei, vid);
|
||||
p->AddHeader(ethHeader);
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::DoDispose()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_node = nullptr;
|
||||
m_channel = nullptr;
|
||||
m_receiveErrorModel = nullptr;
|
||||
m_currentPkt = nullptr;
|
||||
m_queues.clear();
|
||||
NetDevice::DoDispose();
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetDataRate(DataRate bps)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_bps = bps;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::TransmitStart(Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << p);
|
||||
NS_ASSERT_MSG(m_channel != nullptr, "Channel ptr is null");
|
||||
|
||||
NS_LOG_INFO(Names::FindName(this) << " PKT #" << p->GetUid() << " at " << Simulator::Now().GetNanoSeconds()<<" Transmit started ");
|
||||
|
||||
//Add a tag to compute delay between reception(or FIFO enter if first
|
||||
//emission port) and transmission start
|
||||
TimestampTag tag(Simulator::Now());
|
||||
p->AddByteTag(tag);
|
||||
|
||||
//
|
||||
// This function is called to start the process of transmitting a packet.
|
||||
// We need to tell the channel that we've started wiggling the wire and
|
||||
// schedule an event that will be executed when the transmission is complete.
|
||||
//
|
||||
NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit");
|
||||
m_txMachineState = BUSY;
|
||||
m_currentPkt = p;
|
||||
m_phyTxBeginTrace(m_currentPkt);
|
||||
|
||||
Time preambleAndSFDGapTime = m_bps.CalculateBytesTxTime(m_preambleAndSFDGap);
|
||||
Time txTime = m_bps.CalculateBytesTxTime(p->GetSize());
|
||||
Time interpacketGapTime = m_bps.CalculateBytesTxTime(m_interframeGap);
|
||||
Time txCompleteTime = preambleAndSFDGapTime + txTime + interpacketGapTime;
|
||||
|
||||
//NS_LOG_INFO(Names::FindName(this) << " "<< Simulator::Now().GetNanoSeconds()<<" Transmit pkt #"<<p->GetUid());
|
||||
//NS_LOG_LOGIC(Names::FindName(this) << " Schedule TransmitCompleteEvent in " << txCompleteTime.As(Time::S) << " for PKT #" << p->GetUid());
|
||||
Simulator::Schedule(txCompleteTime, &EthernetNetDevice::TransmitComplete, this);
|
||||
|
||||
bool result = m_channel->TransmitStart(p, this, txCompleteTime-interpacketGapTime); //Pkt don't need to wait for the end of Interpacket gap to be considered as receive on the other end of the link
|
||||
if (!result)
|
||||
{
|
||||
m_phyTxDropTrace(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::TransmitComplete()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
NS_LOG_INFO(Names::FindName(this) << " PKT #" << m_currentPkt->GetUid() << " at " << Simulator::Now().GetNanoSeconds()<<" Transmit completed ");
|
||||
// NS_LOG_INFO(Names::FindName(this) << " "<< Simulator::Now().GetNanoSeconds()<<" Transmit completed pkt ");
|
||||
//
|
||||
// This function is called to when we're all done transmitting a packet.
|
||||
// We try and pull another packet off of the transmit queue. If the queue
|
||||
// is empty, we are done, otherwise we need to start transmitting the
|
||||
// next packet.
|
||||
//
|
||||
NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
|
||||
m_txMachineState = READY;
|
||||
|
||||
NS_ASSERT_MSG(m_currentPkt, "EthernetNetDevice::TransmitComplete(): m_currentPkt zero");
|
||||
|
||||
m_phyTxEndTrace(m_currentPkt);
|
||||
|
||||
m_currentPkt = nullptr;
|
||||
|
||||
//Add the event after all the already present at this exact instant to avoid
|
||||
//the beginning of a transmission if a packet will be ready at the event just
|
||||
//after but at the same time instant.
|
||||
Simulator::Schedule(Time(0), &EthernetNetDevice::CheckForReadyPacket, this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EthernetNetDevice::CheckForReadyPacket()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
if (m_txMachineState != READY){
|
||||
return;
|
||||
}
|
||||
|
||||
int next_queue_id = TransmitSelection();
|
||||
if(next_queue_id==-1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Ptr<Packet> p = m_queues[next_queue_id]->Dequeue();
|
||||
//
|
||||
// Got another packet off of the queue, so start the transmit process again.
|
||||
//
|
||||
m_snifferTrace(p);
|
||||
m_promiscSnifferTrace(p);
|
||||
TransmitStart(p);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
EthernetNetDevice::TransmitSelection()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
//For now simple Static Priority Algo
|
||||
for (int i = m_queues.size(); i --> 0; )
|
||||
{
|
||||
if(!m_queues[i]->IsEmpty())
|
||||
{
|
||||
return(i);
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EthernetNetDevice::Attach(Ptr<EthernetChannel> ch)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << &ch);
|
||||
|
||||
m_channel = ch;
|
||||
|
||||
m_channel->Attach(this);
|
||||
|
||||
//
|
||||
// This device is up whenever it is attached to a channel. A better plan
|
||||
// would be to have the link come up when both devices are attached, but this
|
||||
// is not done for now.
|
||||
//
|
||||
NotifyLinkUp();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetQueue(Ptr<Queue<Packet>> q)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << q);
|
||||
m_queues.insert(m_queues.end(),q);
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetReceiveErrorModel(Ptr<ErrorModel> em)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << em);
|
||||
m_receiveErrorModel = em;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::Receive(Ptr<Packet> packet)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << packet);
|
||||
NS_LOG_LOGIC("UID is " << packet->GetUid());
|
||||
if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt(packet))
|
||||
{
|
||||
//
|
||||
// If we have an error model and it indicates that it is time to lose a
|
||||
// corrupted packet, don't forward this packet up, let it go.
|
||||
//
|
||||
NS_LOG_LOGIC("Dropping pkt due to error model ");
|
||||
m_phyRxDropTrace(packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Add timestamp to measure delay in the switches
|
||||
TimestampTag tag(Simulator::Now());
|
||||
packet->AddByteTag(tag);
|
||||
//
|
||||
// Hit the trace hooks. All of these hooks are in the same place in this
|
||||
// device because it is so simple, but this is not usually the case in
|
||||
// more complicated devices.
|
||||
//
|
||||
m_snifferTrace(packet);
|
||||
m_promiscSnifferTrace(packet);
|
||||
m_phyRxEndTrace(packet);
|
||||
|
||||
//
|
||||
// Trace sinks will expect complete packets, not packets without some of the
|
||||
// headers.
|
||||
//
|
||||
Ptr<Packet> originalPacket = packet->Copy();
|
||||
|
||||
EthernetTrailer trailer;
|
||||
packet->RemoveTrailer(trailer);
|
||||
if (Node::ChecksumEnabled())
|
||||
{
|
||||
trailer.EnableFcs(true);
|
||||
}
|
||||
|
||||
bool crcGood = trailer.CheckFcs(packet);
|
||||
if (!crcGood)
|
||||
{
|
||||
NS_LOG_INFO("CRC error on Packet " << packet);
|
||||
m_phyRxDropTrace(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Strip off the ethernet protocol header and forward this packet
|
||||
// up the protocol stack. Since this is a simple point-to-point link,
|
||||
// there is no difference in what the promisc callback sees and what the
|
||||
// normal receive callback sees.
|
||||
//
|
||||
EthernetHeader2 header;
|
||||
packet->RemoveHeader(header);
|
||||
|
||||
uint16_t protocol;
|
||||
protocol = header.GetEthertype();
|
||||
|
||||
//
|
||||
// Classify the packet based on its destination.
|
||||
//
|
||||
PacketType packetType;
|
||||
|
||||
if (header.GetDest() == m_address)
|
||||
{
|
||||
packetType = PACKET_HOST;
|
||||
}
|
||||
else if (header.GetDest().IsGroup())
|
||||
{
|
||||
packetType = PACKET_MULTICAST;
|
||||
}
|
||||
else if (header.GetDest().IsBroadcast())
|
||||
{
|
||||
packetType = PACKET_BROADCAST;
|
||||
}
|
||||
else
|
||||
{
|
||||
packetType = PACKET_OTHERHOST;
|
||||
}
|
||||
|
||||
if (!m_promiscCallback.IsNull())
|
||||
{
|
||||
m_macPromiscRxTrace(originalPacket->Copy());
|
||||
m_promiscCallback(this,
|
||||
originalPacket,
|
||||
protocol,
|
||||
header.GetSrc(),
|
||||
header.GetDest(),
|
||||
packetType);
|
||||
}
|
||||
//
|
||||
// If this packet is not destined for some other host, it must be for us
|
||||
// as either a broadcast, multicast or unicast. We need to hit the mac
|
||||
// packet received trace hook and forward the packet up the stack.
|
||||
//
|
||||
if (packetType != PACKET_OTHERHOST)
|
||||
{
|
||||
//NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << Names::FindName(m_node) << "/" << Names::FindName(this) <<" : Pkt #" << originalPacket->GetUid() <<" received by the netDevice ! " << originalPacket->ToString());
|
||||
m_macRxTrace(originalPacket);
|
||||
m_macRxAnimationTrace(originalPacket, this);
|
||||
m_rxCallback(this, packet, protocol, header.GetSrc());
|
||||
m_latencyTrace(originalPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<Queue<Packet>>
|
||||
EthernetNetDevice::GetQueue(uint8_t index) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_queues[index];
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::NotifyLinkUp()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_linkUp = true;
|
||||
m_linkChangeCallbacks();
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetIfIndex(const uint32_t index)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_ifIndex = index;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
EthernetNetDevice::GetIfIndex() const
|
||||
{
|
||||
return m_ifIndex;
|
||||
}
|
||||
|
||||
Ptr<Channel>
|
||||
EthernetNetDevice::GetChannel() const
|
||||
{
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetAddress(Address address)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << address);
|
||||
m_address = Mac48Address::ConvertFrom(address);
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetAddress() const
|
||||
{
|
||||
return m_address;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EthernetNetDevice::IsLinkUp() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_linkUp;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::AddLinkChangeCallback(Callback<void> callback)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_linkChangeCallbacks.ConnectWithoutContext(callback);
|
||||
}
|
||||
|
||||
//
|
||||
// This is a ethernet device, so every transmission is a broadcast to
|
||||
// all of the devices on the channel.
|
||||
//
|
||||
bool
|
||||
EthernetNetDevice::IsBroadcast() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetBroadcast() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return Mac48Address("ff:ff:ff:ff:ff:ff");
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::IsMulticast() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetMulticast(Ipv4Address multicastGroup) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return Mac48Address("01:00:5e:00:00:00");
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetMulticast(Ipv6Address addr) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this << addr);
|
||||
return Mac48Address("33:33:00:00:00:00");
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::IsPointToPoint() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::IsBridge() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EthernetNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t ethertype)
|
||||
{
|
||||
uint16_t vid = 65535;
|
||||
uint8_t pcp = 0;
|
||||
uint8_t dei = 0;
|
||||
return SendFrom(packet, GetAddress(), dest, ethertype, vid, pcp, dei);
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t ethertype, uint16_t vid, uint8_t pcp, uint8_t dei)
|
||||
{
|
||||
return SendFrom(packet, GetAddress(), dest, ethertype, vid, pcp, dei);
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::SendFrom(Ptr<Packet> packet,
|
||||
const Address& source,
|
||||
const Address& dest,
|
||||
uint16_t ethertype)
|
||||
{
|
||||
//Call by the switch net device with a packet with a EhternetHeader2 and EthernetTrailer
|
||||
//Or by another SendFrom function that have already have a packet with header and trailer
|
||||
// /!\ source, dest, and ethertype are not use in this function but are needed in
|
||||
// the callback define by the netDevice class
|
||||
//
|
||||
// If IsLinkUp() is false it means there is no channel to send any packet
|
||||
// over so we just hit the drop trace on the packet and return an error.
|
||||
//
|
||||
if (!IsLinkUp())
|
||||
{
|
||||
m_macTxDropTrace(packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Add timestamp if first emission
|
||||
TimestampTag tag(Simulator::Now());
|
||||
if (!packet->FindFirstMatchingByteTag(tag))
|
||||
{
|
||||
packet->AddByteTag(tag);
|
||||
}
|
||||
m_macTxTrace(packet);
|
||||
m_macTxAnimationTrace(packet, this);
|
||||
|
||||
Ptr<Packet> pCopy = packet->Copy();
|
||||
EthernetHeader2 header;
|
||||
pCopy->RemoveHeader(header);
|
||||
uint8_t pcp = header.GetPcp();
|
||||
|
||||
NS_ASSERT_MSG(m_queues.size() > pcp, "Not enough fifos ( 0 to "<< m_queues.size()-1 <<") to handle this pcp priority ("<< unsigned(pcp) <<") on Node " <<Names::FindName(GetNode()));
|
||||
|
||||
|
||||
m_FIFOStateSnifferTrace(m_queues, m_txMachineState==BUSY, packet);
|
||||
//
|
||||
// We should enqueue and dequeue the packet to hit the tracing hooks.
|
||||
//
|
||||
if (m_queues[pcp]->Enqueue(packet))
|
||||
{
|
||||
NS_LOG_INFO(Names::FindName(this) << " Enqueue pkt #"<<packet->GetUid() << " OK !");
|
||||
//Add the event after all the already present at this exact instant to avoid
|
||||
//the beginning of a transmission if a packet will be ready at the event just
|
||||
//after but at the same time instant.
|
||||
Simulator::Schedule(Time(0), &EthernetNetDevice::CheckForReadyPacket, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Enqueue may fail (overflow)
|
||||
m_macTxDropTrace(packet);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t ethertype, uint16_t vid, uint8_t pcp, uint8_t dei)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << packet << dest << ethertype);
|
||||
NS_LOG_LOGIC(Names::FindName(this) << " p=" << packet->GetUid() << ", dest=" << &dest);
|
||||
|
||||
// NS_LOG_INFO(Names::FindName(this) << " SendFrom : p=" << packet->GetUid() << ", dest=" << &dest << " at " << Simulator::Now());
|
||||
|
||||
|
||||
if (vid == 65535){
|
||||
AddHeader(packet, Mac48Address::ConvertFrom(dest), Mac48Address::ConvertFrom(source), ethertype);
|
||||
}
|
||||
else{
|
||||
AddHeader(packet, Mac48Address::ConvertFrom(dest), Mac48Address::ConvertFrom(source), ethertype, vid, pcp, dei);
|
||||
}
|
||||
|
||||
EthernetTrailer trailer;
|
||||
trailer.EnableFcs(true);
|
||||
trailer.CalcFcs(packet);
|
||||
packet->AddTrailer(trailer);
|
||||
|
||||
|
||||
return SendFrom(packet, source, dest, ethertype);
|
||||
}
|
||||
|
||||
Ptr<Node>
|
||||
EthernetNetDevice::GetNode() const
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetNode(Ptr<Node> node)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
m_node = node;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::NeedsArp() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb)
|
||||
{
|
||||
m_rxCallback = cb;
|
||||
}
|
||||
|
||||
void
|
||||
EthernetNetDevice::SetPromiscReceiveCallback(NetDevice::PromiscReceiveCallback cb)
|
||||
{
|
||||
m_promiscCallback = cb;
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::SupportsSendFrom() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
Address
|
||||
EthernetNetDevice::GetRemote() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
NS_ASSERT(m_channel->GetNDevices() == 2);
|
||||
for (std::size_t i = 0; i < m_channel->GetNDevices(); ++i)
|
||||
{
|
||||
Ptr<NetDevice> tmp = m_channel->GetDevice(i);
|
||||
if (tmp != this)
|
||||
{
|
||||
return tmp->GetAddress();
|
||||
}
|
||||
}
|
||||
NS_ASSERT(false);
|
||||
// quiet compiler.
|
||||
return Address();
|
||||
}
|
||||
|
||||
bool
|
||||
EthernetNetDevice::SetMtu(uint16_t mtu)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << mtu);
|
||||
m_mtu = mtu;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
EthernetNetDevice::GetMtu() const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_mtu;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user