#include "tsn-multidrop-channel.h" #include "tsn-multidrop-net-device.h" #include "ns3/log.h" #include "ns3/packet.h" #include "ns3/simulator.h" #include "ns3/trace-source-accessor.h" namespace ns3 { NS_LOG_COMPONENT_DEFINE("TsnMultidropChannel"); NS_OBJECT_ENSURE_REGISTERED(TsnMultidropChannel); TypeId TsnMultidropChannel::GetTypeId() { static TypeId tid = TypeId("ns3::TsnMultidropChannel") .SetParent() .SetGroupName("Tsn") .AddConstructor() .AddAttribute("Delay", "Propagation delay through the channel", TimeValue(NanoSeconds(25)), MakeTimeAccessor(&TsnMultidropChannel::m_delay), MakeTimeChecker()) .AddTraceSource("TxRxEthernet", "Trace source indicating transmission of packet " "from the TsnMultidropChannel, used by the Animation " "interface.", MakeTraceSourceAccessor(&TsnMultidropChannel::m_txrxEthernet), "ns3::TsnMultidropChannel::TxRxAnimationCallback"); return tid; } TsnMultidropChannel::TsnMultidropChannel() : Channel() { NS_LOG_FUNCTION_NOARGS(); } void TsnMultidropChannel::Attach(Ptr device) { NS_LOG_FUNCTION(this << device); NS_ASSERT(device); NS_ASSERT(m_netDevices.size() < 255); //Limitation from IEEE802.3cg-2019 m_netDevices.insert(m_netDevices.end(), device); //If we have two devices connected to the channel, the channel is usable if (m_netDevices.size() >= 2) { m_wireState = IDLE; } } bool TsnMultidropChannel::TransmitStart(Ptr p, Ptr src, Time txTime) { NS_LOG_FUNCTION(this << p << src); NS_LOG_LOGIC("UID is " << p->GetUid() << ")"); NS_ASSERT(m_wireState == IDLE); for (std::size_t i = 0; i < m_netDevices.size(); ++i) { if(m_netDevices[i]!=src) { //Start of reception => Change PLCA state m_netDevices[i]->StartReception(); //Schedule reception a the end of the transmission Simulator::ScheduleWithContext(m_netDevices[i]->GetNode()->GetId(), txTime + m_delay, &TsnMultidropNetDevice::Receive, m_netDevices[i], p->Copy()); NS_LOG_INFO(txTime + m_delay); } } // Call the tx anim callback on the net device // m_txrxEthernet(p, src, m_wire[wire].m_dst, txTime, txTime + m_delay); return true; } std::size_t TsnMultidropChannel::GetNDevices() const { NS_LOG_FUNCTION_NOARGS(); return m_netDevices.size(); } Ptr TsnMultidropChannel::GetEthernetDevice(std::size_t i) const { NS_LOG_FUNCTION_NOARGS(); NS_ASSERT(i < m_netDevices.size()); return m_netDevices[i]; } Ptr TsnMultidropChannel::GetDevice(std::size_t i) const { NS_LOG_FUNCTION_NOARGS(); return GetEthernetDevice(i); } Time TsnMultidropChannel::GetDelay() const { return m_delay; } bool TsnMultidropChannel::IsInitialized() const { NS_ASSERT(m_wireState != INITIALIZING); return true; } void TsnMultidropChannel::StartBeaconTransmission() { NS_LOG_FUNCTION(this); NS_ASSERT(m_wireState == IDLE); m_wireState = TRANSMITTING; for (std::size_t i = 0; i < m_netDevices.size(); ++i) { m_netDevices[i]->StartBeaconReception(); } } void TsnMultidropChannel::StopBeaconTransmission() { NS_LOG_FUNCTION(this); NS_ASSERT(m_wireState == TRANSMITTING); m_wireState = IDLE; for (std::size_t i = 0; i < m_netDevices.size(); ++i) { m_netDevices[i]->StopBeaconReception(); } } }