diff --git a/helper/dummy-switch-helper.cc b/helper/dummy-switch-helper.cc index 9873e23..0373357 100644 --- a/helper/dummy-switch-helper.cc +++ b/helper/dummy-switch-helper.cc @@ -34,15 +34,16 @@ DummySwitchHelper::DummySwitchHelper() } void -DummySwitchHelper::SetDeviceAttribute(std::string n1, const AttributeValue& v1) +DummySwitchHelper::SetDeviceAttribute(const std::string& n1, const AttributeValue& v1) { NS_LOG_FUNCTION(this << n1); m_deviceFactory.Set(n1, v1); } Ptr -DummySwitchHelper::Install(Ptr node, NetDeviceContainer portDevices) +DummySwitchHelper::Install(Ptr node, const NetDeviceContainer& portDevices) { + NS_ASSERT_MSG(node != nullptr, "Invalid node pointer passed to DummySwitchHelper::Install"); NS_LOG_FUNCTION(this << node); Ptr dev = m_deviceFactory.Create(); @@ -59,10 +60,12 @@ DummySwitchHelper::Install(Ptr node, NetDeviceContainer portDevices) } Ptr -DummySwitchHelper::Install(std::string nodeName, NetDeviceContainer portDevices) +DummySwitchHelper::Install(const std::string& nodeName, const NetDeviceContainer& portDevices) { NS_LOG_FUNCTION(this << nodeName); Ptr node = Names::Find(nodeName); + NS_ASSERT_MSG(node != nullptr, + "DummySwitchHelper::Install: node '" << nodeName << "' not found"); return Install(node, portDevices); } diff --git a/helper/dummy-switch-helper.h b/helper/dummy-switch-helper.h index cbc041f..e9537f7 100644 --- a/helper/dummy-switch-helper.h +++ b/helper/dummy-switch-helper.h @@ -45,7 +45,7 @@ class DummySwitchHelper * \param n1 attribute name * \param v1 attribute value */ - void SetDeviceAttribute(std::string n1, const AttributeValue& v1); + void SetDeviceAttribute(const std::string& n1, const AttributeValue& v1); /** * \brief Install a DummySwitchNetDevice on a node. @@ -58,7 +58,7 @@ class DummySwitchHelper * \return the created DummySwitchNetDevice */ Ptr Install(Ptr node, - NetDeviceContainer portDevices); + const NetDeviceContainer& portDevices); /** * \brief Install a DummySwitchNetDevice on a node (by name). @@ -66,8 +66,8 @@ class DummySwitchHelper * \param portDevices the NetDevices to add as switch ports * \return the created DummySwitchNetDevice */ - Ptr Install(std::string nodeName, - NetDeviceContainer portDevices); + Ptr Install(const std::string& nodeName, + const NetDeviceContainer& portDevices); private: ObjectFactory m_deviceFactory; //!< Factory for creating DummySwitchNetDevice diff --git a/model/dummy-switch-helper.cc b/model/dummy-switch-helper.cc deleted file mode 100644 index 9873e23..0000000 --- a/model/dummy-switch-helper.cc +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2025 TU Dresden - * - * 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: Mingyu Ma - */ - -#include "ns3/dummy-switch-helper.h" - -#include "ns3/log.h" -#include "ns3/names.h" - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("DummySwitchHelper"); - -DummySwitchHelper::DummySwitchHelper() -{ - NS_LOG_FUNCTION(this); - m_deviceFactory.SetTypeId("ns3::DummySwitchNetDevice"); -} - -void -DummySwitchHelper::SetDeviceAttribute(std::string n1, const AttributeValue& v1) -{ - NS_LOG_FUNCTION(this << n1); - m_deviceFactory.Set(n1, v1); -} - -Ptr -DummySwitchHelper::Install(Ptr node, NetDeviceContainer portDevices) -{ - NS_LOG_FUNCTION(this << node); - - Ptr dev = m_deviceFactory.Create(); - node->AddDevice(dev); - - for (uint32_t i = 0; i < portDevices.GetN(); i++) - { - dev->AddPort(portDevices.Get(i)); - } - - NS_LOG_INFO("Installed DummySwitchNetDevice on node " << node->GetId() - << " with " << portDevices.GetN() << " ports"); - return dev; -} - -Ptr -DummySwitchHelper::Install(std::string nodeName, NetDeviceContainer portDevices) -{ - NS_LOG_FUNCTION(this << nodeName); - Ptr node = Names::Find(nodeName); - return Install(node, portDevices); -} - -} // namespace ns3 diff --git a/model/dummy-switch-helper.h b/model/dummy-switch-helper.h deleted file mode 100644 index cbc041f..0000000 --- a/model/dummy-switch-helper.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2025 TU Dresden - * - * 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: Mingyu Ma - */ - -#ifndef DUMMY_SWITCH_HELPER_H -#define DUMMY_SWITCH_HELPER_H - -#include "ns3/dummy-switch-net-device.h" -#include "ns3/net-device-container.h" -#include "ns3/node.h" -#include "ns3/object-factory.h" - -namespace ns3 -{ - -/** - * \ingroup p4sim - * \brief Helper to install DummySwitchNetDevice on nodes. - * - * DummySwitchHelper simplifies creating and configuring a DummySwitchNetDevice. - * It follows the same pattern as P4Helper and BridgeHelper. - */ -class DummySwitchHelper -{ - public: - DummySwitchHelper(); - - /** - * \brief Set an attribute on the DummySwitchNetDevice. - * \param n1 attribute name - * \param v1 attribute value - */ - void SetDeviceAttribute(std::string n1, const AttributeValue& v1); - - /** - * \brief Install a DummySwitchNetDevice on a node. - * - * Creates a DummySwitchNetDevice, adds each NetDevice in the container - * as a port, and installs the switch on the node. - * - * \param node the node to install on - * \param portDevices the NetDevices to add as switch ports - * \return the created DummySwitchNetDevice - */ - Ptr Install(Ptr node, - NetDeviceContainer portDevices); - - /** - * \brief Install a DummySwitchNetDevice on a node (by name). - * \param nodeName the name of the node - * \param portDevices the NetDevices to add as switch ports - * \return the created DummySwitchNetDevice - */ - Ptr Install(std::string nodeName, - NetDeviceContainer portDevices); - - private: - ObjectFactory m_deviceFactory; //!< Factory for creating DummySwitchNetDevice -}; - -} // namespace ns3 - -#endif /* DUMMY_SWITCH_HELPER_H */ diff --git a/model/dummy-switch-port.cc b/model/dummy-switch-port.cc index dd364de..5390447 100644 --- a/model/dummy-switch-port.cc +++ b/model/dummy-switch-port.cc @@ -21,6 +21,7 @@ #include "ns3/log.h" #include "ns3/queue-disc.h" +#include "ns3/queue-item.h" #include "ns3/uinteger.h" namespace ns3 @@ -29,6 +30,51 @@ namespace ns3 NS_LOG_COMPONENT_DEFINE("DummySwitchPort"); NS_OBJECT_ENSURE_REGISTERED(DummySwitchPort); +// ============================================================================= +// DummySwitchQueueItem — concrete QueueDiscItem for L2 switch forwarding +// ============================================================================= + +/** + * \brief A minimal concrete QueueDiscItem for use in DummySwitchPort. + * + * ns3::QueueDiscItem is abstract (pure virtual AddHeader() and Mark()). + * This subclass provides trivial implementations since the dummy switch + * operates at L2 and does not need to manipulate headers or support ECN + * marking. + */ +class DummySwitchQueueItem : public QueueDiscItem +{ + public: + /** + * \brief Construct a DummySwitchQueueItem. + * \param p the packet + * \param addr the destination MAC address + * \param protocol the L3 protocol number (EtherType) + */ + DummySwitchQueueItem(Ptr p, const Address& addr, uint16_t protocol) + : QueueDiscItem(p, addr, protocol) + { + } + + /** No header manipulation needed for L2 forwarding. */ + void AddHeader() override + { + } + + /** + * \brief ECN marking is not supported by the dummy switch. + * \return always false + */ + bool Mark() override + { + return false; + } +}; + +// ============================================================================= +// DummySwitchPort implementation +// ============================================================================= + TypeId DummySwitchPort::GetTypeId() { @@ -93,6 +139,10 @@ DummySwitchPort::SetTrafficManager(Ptr qdisc) { NS_LOG_FUNCTION(this << qdisc); m_egressTm = qdisc; + if (qdisc && !qdisc->IsInitialized()) + { + qdisc->Initialize(); + } NS_LOG_INFO("Port " << m_portId << ": Traffic manager " << (qdisc ? "attached" : "detached")); } @@ -143,20 +193,30 @@ DummySwitchPort::EnqueueEgress(Ptr packet, if (m_egressTm) { - // Enqueue through the traffic manager + // Wrap packet in a QueueDiscItem and enqueue through the traffic manager + Ptr item = + Create(packet, dest, protocolNumber); + NS_LOG_DEBUG("Port " << m_portId << ": enqueueing packet (size " - << packet->GetSize() << ") into traffic manager"); - // NOTE: Full QueueDisc integration requires QueueDiscItem wrapping. - // For the skeleton, we bypass the TM and send directly, but log - // that the TM is present. - NS_LOG_INFO("Port " << m_portId << ": TM present (" - << m_egressTm->GetInstanceTypeId().GetName() - << "), forwarding packet directly for now"); + << packet->GetSize() << ") into traffic manager (" + << m_egressTm->GetInstanceTypeId().GetName() << ")"); + + bool enqueued = m_egressTm->Enqueue(item); + if (!enqueued) + { + NS_LOG_DEBUG("Port " << m_portId + << ": traffic manager dropped packet (queue full)"); + return false; + } + + // Immediately try to dequeue and transmit + TransmitFromQueue(); + return true; } - // Send directly on the underlying NetDevice + // No traffic manager — send directly on the underlying NetDevice NS_LOG_DEBUG("Port " << m_portId << ": sending packet (size " - << packet->GetSize() << ") on " + << packet->GetSize() << ") on " << m_netDevice->GetInstanceTypeId().GetName()); return m_netDevice->Send(packet, dest, protocolNumber); @@ -166,10 +226,26 @@ void DummySwitchPort::TransmitFromQueue() { NS_LOG_FUNCTION(this); - // Placeholder: will be used when full QueueDisc integration is implemented. - // The QueueDisc dequeue callback would invoke this method to actually - // transmit the packet on the underlying NetDevice. - NS_LOG_DEBUG("Port " << m_portId << ": TransmitFromQueue called (placeholder)"); + + if (!m_egressTm || !m_netDevice) + { + return; + } + + // Dequeue all available packets and transmit them + Ptr item = m_egressTm->Dequeue(); + while (item) + { + Ptr packet = item->GetPacket(); + Address dest = item->GetAddress(); + uint16_t protocol = item->GetProtocol(); + + NS_LOG_DEBUG("Port " << m_portId << ": dequeued packet (size " + << packet->GetSize() << ") from traffic manager"); + + m_netDevice->Send(packet, dest, protocol); + item = m_egressTm->Dequeue(); + } } } // namespace ns3