diff --git a/CMakeLists.txt b/CMakeLists.txt index 7953c49..0592252 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ endif() # Check for BOFUSS dependency -# List of BOFUSS headers files required by OFSwtich13 +# List of BOFUSS headers files required by OFSwitch13 set(NS3_OFSWITCH13_BOFUSS_HEADERS bofuss/action_set.h bofuss/datapath.h @@ -73,7 +73,7 @@ if(NOT bofuss_FOUND AND NOT ${bofuss_FOUND}) ExternalProject_Add( bofuss_dep GIT_REPOSITORY https://github.com/ljerezchaves/ofsoftswitch13.git - GIT_TAG 0901aeb7f1612016e43e774381507c2aaef4afc2 + GIT_TAG 1b6106e3e3814c50b323e43b6bb2dec5ab13ffe7 PREFIX bofuss_dep BUILD_IN_SOURCE TRUE UPDATE_DISCONNECTED TRUE @@ -143,11 +143,12 @@ set(header_files set(test_sources ) -# Library to link the OFSwitch13 module +# Libraries to link to the OFSwitch13 module set(libraries_to_link - ${libcsma} + ${libcore} + ${libnetwork} ${libinternet} - ${libapplications} + ${libcsma} ${libpoint-to-point} ${libvirtual-net-device} ${bofuss_LIBRARIES} @@ -162,7 +163,7 @@ build_lib( TEST_SOURCES ${test_sources} ) -# Add BOFUSS dependecy to OFswitch13 module +# Add BOFUSS dependecy to OFSwitch13 module if(NOT bofuss_FOUND AND NOT ${bofuss_FOUND}) add_dependencies(${libofswitch13} bofuss_dep) if(NOT ${XCODE}) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 03e8f1d..ecc814f 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -4,15 +4,30 @@ OFSwitch13 release notes This file contains OFSwitch13 release notes (most recent releases first). +Release 5.2.2 (Sep 01, 2023) +============================ + +- Removing examples/ofswitch13-qos-controller dependency from netanim module. + +- Updating buffer timeout operation with millisecond resolution. + +- Updating the maximum size of the parent OFSwitch13Queue class with the sum of + maximum size of internal queues. The operation mode (packets or bytes) of all + internal queues must be the same. + +- This version is compatible with ns-3 versions 3.38 and 3.39 (including + patches). There is no backward compatibility with older ns-3 versions. + +- Compilation was tested in Ubuntu 22.04.1 LTS. + Release 5.2.1 (Mar 31, 2023) ============================ - Replacing V4PingHelper by PingHelper in examples for ns-3.38 compatibility. -- This version is compatible with BOFUSS library release v5.2.x and ns-3 - version 3.38 (including patches). There is no backward compatibility with - older ns-3 versions. +- This version is compatible with ns-3 version 3.38 (including patches). There + is no backward compatibility with older ns-3 versions. - Compilation was tested in Ubuntu 22.04.1 LTS. @@ -23,16 +38,15 @@ Release 5.2.0 (Mar 31, 2023) - Updating CMakeLists.txt to automatically download and build the BOFUSS library. -- Updating the module documentation to reflext the changes in library building. +- Updating the module documentation to reflect the changes in library building. - Replacing the outdated ofsoftswitch13 library name by BOFUSS in the project (source code and documentation). - Refactoring the BOFUSS ns3lib branch to simplify library compilation. -- This version is compatible with BOFUSS library release v5.2.x and ns-3 - versions 3.36 and 3.37 (including patches). There is no backward - compatibility with older ns-3 versions. +- This version is compatible with ns-3 versions 3.36 and 3.37 (including + patches). There is no backward compatibility with older ns-3 versions. - Compilation was tested in Ubuntu 22.04.1 LTS. @@ -77,17 +91,17 @@ Release 5.0.0 (Dec 19, 2021) - BE AWARE THAT this release brings incompatible API changes in respect to prior OFSwitch13 versions. -- Refactoring OFSwitch13Controller::Dpctl* () methods: - * The DpctlExecute () method has no more overloaded definitions. The target +- Refactoring OFSwitch13Controller::Dpctl*() methods: + * The DpctlExecute() method has no more overloaded definitions. The target switch (first parameter) must be the switch's datapath IP. Previous signature using the Ptr swtch pointer was removed. - Users can fix compilation errors by just using swtch->GetDpId () when - invoking DpctlExecute (); - * The DpctlSchedule () method was deprecated in favor of DpctlExecute (). - When the switch is not connected to the controller, the DpctlExecute () + Users can fix compilation errors by just using swtch->GetDpId() when + invoking DpctlExecute(); + * The DpctlSchedule() method was deprecated in favor of DpctlExecute(). + When the switch is not connected to the controller, the DpctlExecute() will automatically schedule the command for execution just after the handshake procedure. This is particularly useful for executing dpctl - commands when creating the topology, before invoking Simulator::Run (). + commands when creating the topology, before invoking Simulator::Run(). - Creating a new OFSwitch13Device::TableDrop trace source to notify unmatched packets dropped by flow tables without table-miss entries. A new TabDrps @@ -356,7 +370,7 @@ Release 3.0.0 (Feb 10, 2017) - Removing the controller address attribute from the OpenFlow device. It now must be indicated by the helper as a parameter to the - StartControllerConnection () device method. + StartControllerConnection() device method. - Creating the OFSwitch13StatsCalculator for switch performance monitoring. @@ -372,7 +386,7 @@ Release 3.0.0 (Feb 10, 2017) - Refactoring the OFSwitch13Controller class: * Splitting the DpctlCommand into 'execute' and 'schedule' versions; * Removing dependence from OFSwitch13Device class; - * Renaming ConnectionStarted () method to HandshakeSuccessful () to reflect + * Renaming ConnectionStarted() method to HandshakeSuccessful() to reflect the method semantic; * Implementing the handshake procedure; * Implementing barrier reply, hello and features reply handlers; @@ -386,7 +400,7 @@ Release 3.0.0 (Feb 10, 2017) * Supporting the configuration of OpenFlow networks domains with multiple controllers; * Removing the dependence of installing the controller before the switches; - * Introducing the CreateOpenFlowChannels () member function to effectively + * Introducing the CreateOpenFlowChannels() member function to effectively connect switches to controllers after installing switches and controllers into respective nodes (the use of this function is mandatory). diff --git a/doc/source/conf.py b/doc/source/conf.py index bce8441..1b5a32b 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -73,9 +73,9 @@ # built documents. # # The short X.Y version. -version = u'5.2.1' +version = u'5.2.2' # The full version, including alpha/beta/rc tags. -release = u'5.2.1' +release = u'5.2.2' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/source/ofswitch13-description.rst b/doc/source/ofswitch13-description.rst index 38c6cbd..1c6bfe9 100644 --- a/doc/source/ofswitch13-description.rst +++ b/doc/source/ofswitch13-description.rst @@ -204,8 +204,8 @@ For |ns3| OpenFlow users who want to port existing code to this new module, plea The only required modification to the |ns3| source code for |ofs13| integration is the inclusion of the new OpenFlow receive callback in the ``CsmaNetDevice`` and ``VirtualNetDevice``. The module brings the patch for including this receive callback into |ns3| source code, available under ``utils/`` directory. -The current |ofs13| stable version is 5.2.1. -This version is compatible with |ns3| version 3.38, and will not compile with older |ns3| versions. +The current |ofs13| stable version is 5.2.2. +This version is compatible with |ns3| versions 3.38 and 3.39, and will not compile with older |ns3| versions. If you need to use another |ns3| release, you can check the RELEASE_NOTES file for previous |ofs13| releases and their |ns3| version compatibility, but keep in mind that old releases may have known bugs and an old API. It is strongly recommended to use the latest module version. diff --git a/doc/source/ofswitch13-usage.rst b/doc/source/ofswitch13-usage.rst index 88a8035..a88b21b 100644 --- a/doc/source/ofswitch13-usage.rst +++ b/doc/source/ofswitch13-usage.rst @@ -32,13 +32,13 @@ Before starting, ensure you have the following minimal requirements installed on Compiling the code ################## -Clone the |ns3| source code repository into your machine and checkout a stable version (we are using the ns-3.38): +Clone the |ns3| source code repository into your machine and checkout a stable version (we are using the ns-3.39): .. code-block:: bash $ git clone https://gitlab.com/nsnam/ns-3-dev.git $ cd ns-3-dev - $ git checkout -b ns-3.38 ns-3.38 + $ git checkout -b ns-3.39 ns-3.39 Download the |ofs13| code into the ``contrib/`` folder. @@ -47,7 +47,7 @@ Download the |ofs13| code into the ``contrib/`` folder. $ cd contrib/ $ git clone https://github.com/ljerezchaves/ofswitch13.git -Update the |ofs13| code to a stable version (we are using release 5.2.1, which is compatible with ns-3.38) [#f2]_: +Update the |ofs13| code to a stable version (we are using release 5.2.2, which is compatible with ns-3.39) [#f2]_: .. [#f2] Starting at |ofs13| release 5.2.0, the ``cmake`` build system will automatically download and compile the correct version of |bofuss| library (Internet connection is required). For older |ofs13| releases, we suggest you check the documentation and follow the proper build steps. @@ -55,14 +55,14 @@ Update the |ofs13| code to a stable version (we are using release 5.2.1, which i .. code-block:: bash $ cd ofswitch13 - $ git checkout 5.2.1 + $ git checkout 5.2.2 Go back to the |ns3| root directory and patch the |ns3| code with the appropriated ``ofswitch13`` patch available under the ``ofswitch13/utils/`` directory (check for the correct |ns3| version): .. code-block:: bash $ cd ../../ - $ patch -p1 < contrib/ofswitch13/utils/ofswitch13-3_38.patch + $ patch -p1 < contrib/ofswitch13/utils/ofswitch13-3_39.patch This patch creates the new OpenFlow receive callback at ``CsmaNetDevice`` and ``VirtualNetDevice``, allowing OpenFlow switch to get raw packets from these devices. The module also brings a ``csma-full-duplex`` patch for improving CSMA connections with full-duplex support. @@ -93,68 +93,68 @@ This script connects two hosts to a single OpenFlow switch using CSMA links, and .. code-block:: cpp #include - #include #include + #include #include + #include #include - #include using namespace ns3; int - main (int argc, char *argv[]) + main(int argc, char* argv[]) { - // Enable checksum computations (required by OFSwitch13 module) - GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true)); + // Enable checksum computations (required by OFSwitch13 module) + GlobalValue::Bind("ChecksumEnabled", BooleanValue(true)); - // Create two host nodes - NodeContainer hosts; - hosts.Create (2); + // Create two host nodes + NodeContainer hosts; + hosts.Create(2); - // Create the switch node - Ptr switchNode = CreateObject (); + // Create the switch node + Ptr switchNode = CreateObject(); - // Use the CsmaHelper to connect the host nodes to the switch. - CsmaHelper csmaHelper; - NetDeviceContainer hostDevices; - NetDeviceContainer switchPorts; - for (size_t i = 0; i < hosts.GetN (); i++) + // Use the CsmaHelper to connect the host nodes to the switch. + CsmaHelper csmaHelper; + NetDeviceContainer hostDevices; + NetDeviceContainer switchPorts; + for (size_t i = 0; i < hosts.GetN(); i++) { - NodeContainer pair (hosts.Get (i), switchNode); - NetDeviceContainer link = csmaHelper.Install (pair); - hostDevices.Add (link.Get (0)); - switchPorts.Add (link.Get (1)); + NodeContainer pair(hosts.Get(i), switchNode); + NetDeviceContainer link = csmaHelper.Install(pair); + hostDevices.Add(link.Get(0)); + switchPorts.Add(link.Get(1)); } - // Create the controller node - Ptr controllerNode = CreateObject (); - - // Configure the OpenFlow network domain - Ptr of13Helper = CreateObject (); - of13Helper->InstallController (controllerNode); - of13Helper->InstallSwitch (switchNode, switchPorts); - of13Helper->CreateOpenFlowChannels (); - - // Install the TCP/IP stack into hosts nodes - InternetStackHelper internet; - internet.Install (hosts); - - // Set IPv4 host addresses - Ipv4AddressHelper ipv4helpr; - Ipv4InterfaceContainer hostIpIfaces; - ipv4helpr.SetBase ("10.1.1.0", "255.255.255.0"); - hostIpIfaces = ipv4helpr.Assign (hostDevices); - - // Configure ping application between hosts - PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); - pingHelper.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE)); - ApplicationContainer pingApps = pingHelper.Install (hosts.Get (0)); - pingApps.Start (Seconds (1)); - - // Run the simulation - Simulator::Stop (Seconds (10)); - Simulator::Run (); - Simulator::Destroy (); + // Create the controller node + Ptr controllerNode = CreateObject(); + + // Configure the OpenFlow network domain + Ptr of13Helper = CreateObject(); + of13Helper->InstallController(controllerNode); + of13Helper->InstallSwitch(switchNode, switchPorts); + of13Helper->CreateOpenFlowChannels(); + + // Install the TCP/IP stack into hosts nodes + InternetStackHelper internet; + internet.Install(hosts); + + // Set IPv4 host addresses + Ipv4AddressHelper ipv4Helper; + Ipv4InterfaceContainer hostIpIfaces; + ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); + hostIpIfaces = ipv4Helper.Assign(hostDevices); + + // Configure ping application between hosts + PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); + pingHelper.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE)); + ApplicationContainer pingApps = pingHelper.Install(hosts.Get(0)); + pingApps.Start(Seconds(1)); + + // Run the simulation + Simulator::Stop(Seconds(10)); + Simulator::Run(); + Simulator::Destroy(); } At first, don't forget to enable checksum computations, which are required by the |ofs13| module. @@ -369,14 +369,14 @@ The following code, based on the ``openflow-switch.cc`` example, is used for dem // Create the learning controller app Ptr controller; - controller = CreateObject (); - if (!timeout.IsZero ()) + controller = CreateObject(); + if (!timeout.IsZero()) { - controller->SetAttribute ("ExpirationTime", TimeValue (timeout)); + controller->SetAttribute("ExpirationTime", TimeValue(timeout)); } // Install the switch device, ports and set the controller - ofHelper.Install (switchNode, switchDevices, controller); + ofHelper.Install(switchNode, switchDevices, controller); // Other configurations: TCP/IP stack, apps, monitors, etc. // ... @@ -396,23 +396,23 @@ The following code implements the same logic in the |ofs13| module: // ... // Create the OpenFlow 1.3 helper - Ptr of13Helper = CreateObject (); + Ptr of13Helper = CreateObject(); // Create the controller node and install the learning controller app into it - Ptr controllerNode = CreateObject (); - of13Helper->InstallController (controllerNode); + Ptr controllerNode = CreateObject(); + of13Helper->InstallController(controllerNode); // Install the switch device and ports. - of13Helper->InstallSwitch (switchNode, switchDevices); + of13Helper->InstallSwitch(switchNode, switchDevices); // Create the OpenFlow channel connections. - of13Helper->CreateOpenFlowChannels (); + of13Helper->CreateOpenFlowChannels(); // Other configurations: TCP/IP stack, apps, monitors, etc. // ... // Arbitrary simulation duration (can be changed for any value) - Simulator::Stop (Seconds (10)); + Simulator::Stop(Seconds(10)); Note that the |ofs13| module requires a new node to install the controller application into it. The ``InstallController()`` function creates the learning application object instance and installs it in the ``controllerNode``. @@ -480,18 +480,18 @@ The experimental ``external-controller.cc`` example uses the ``OFSwitch13Externa // ... // Configure the OpenFlow network domain using an external controller - Ptr of13Helper = CreateObject (); - Ptr ctrlDev = of13Helper->InstallExternalController (controllerNode); - of13Helper->InstallSwitch (switches.Get (0), switchPorts [0]); - of13Helper->InstallSwitch (switches.Get (1), switchPorts [1]); - of13Helper->CreateOpenFlowChannels (); + Ptr of13Helper = CreateObject(); + Ptr ctrlDev = of13Helper->InstallExternalController(controllerNode); + of13Helper->InstallSwitch(switches.Get(0), switchPorts [0]); + of13Helper->InstallSwitch(switches.Get(1), switchPorts [1]); + of13Helper->CreateOpenFlowChannels(); // TapBridge the controller device to local machine // The default configuration expects a controller on local port 6653 TapBridgeHelper tapBridge; - tapBridge.SetAttribute ("Mode", StringValue ("ConfigureLocal")); - tapBridge.SetAttribute ("DeviceName", StringValue ("ctrl")); - tapBridge.Install (controllerNode, ctrlDev); + tapBridge.SetAttribute("Mode", StringValue("ConfigureLocal")); + tapBridge.SetAttribute("DeviceName", StringValue("ctrl")); + tapBridge.Install(controllerNode, ctrlDev); // ... diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 9d1edea..06c70c7 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -53,7 +53,7 @@ build_lib_example( ofswitch13-qos-controller/qos-controller.cc LIBRARIES_TO_LINK ${libofswitch13} - ${libnetanim} + ${libapplications} ) build_lib_example( diff --git a/examples/ofswitch13-custom-switch.cc b/examples/ofswitch13-custom-switch.cc index 3b59fb1..e4bdada 100644 --- a/examples/ofswitch13-custom-switch.cc +++ b/examples/ofswitch13-custom-switch.cc @@ -124,10 +124,10 @@ main(int argc, char* argv[]) internet.Install(hosts); // Set IPv4 host addresses - Ipv4AddressHelper ipv4helpr; + Ipv4AddressHelper ipv4Helper; Ipv4InterfaceContainer hostIpIfaces; - ipv4helpr.SetBase("10.1.1.0", "255.255.255.0"); - hostIpIfaces = ipv4helpr.Assign(hostDevices); + ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); + hostIpIfaces = ipv4Helper.Assign(hostDevices); // Configure ping application between hosts PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); diff --git a/examples/ofswitch13-external-controller.cc b/examples/ofswitch13-external-controller.cc index 32bb655..2bb6c66 100644 --- a/examples/ofswitch13-external-controller.cc +++ b/examples/ofswitch13-external-controller.cc @@ -153,10 +153,10 @@ main(int argc, char* argv[]) internet.Install(hosts); // Set IPv4 host addresses - Ipv4AddressHelper ipv4helpr; + Ipv4AddressHelper ipv4Helper; Ipv4InterfaceContainer hostIpIfaces; - ipv4helpr.SetBase("10.1.1.0", "255.255.255.0"); - hostIpIfaces = ipv4helpr.Assign(hostDevices); + ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); + hostIpIfaces = ipv4Helper.Assign(hostDevices); // Random number generators for ping applications Ptr randomHostRng = CreateObject(); diff --git a/examples/ofswitch13-first.cc b/examples/ofswitch13-first.cc index 6eac7f4..b0a2297 100644 --- a/examples/ofswitch13-first.cc +++ b/examples/ofswitch13-first.cc @@ -105,10 +105,10 @@ main(int argc, char* argv[]) internet.Install(hosts); // Set IPv4 host addresses - Ipv4AddressHelper ipv4helpr; + Ipv4AddressHelper ipv4Helper; Ipv4InterfaceContainer hostIpIfaces; - ipv4helpr.SetBase("10.1.1.0", "255.255.255.0"); - hostIpIfaces = ipv4helpr.Assign(hostDevices); + ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); + hostIpIfaces = ipv4Helper.Assign(hostDevices); // Configure ping application between hosts PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); diff --git a/examples/ofswitch13-logical-port/gtp-tunnel-app.cc b/examples/ofswitch13-logical-port/gtp-tunnel-app.cc index 75ad947..124808f 100644 --- a/examples/ofswitch13-logical-port/gtp-tunnel-app.cc +++ b/examples/ofswitch13-logical-port/gtp-tunnel-app.cc @@ -46,9 +46,12 @@ GtpTunnelApp::~GtpTunnelApp() TypeId GtpTunnelApp::GetTypeId() { - static TypeId tid = - TypeId("ns3::GtpTunnelApp").SetParent().SetGroupName("OFSwitch13"); + // clang-format off + static TypeId tid = TypeId("ns3::GtpTunnelApp") + .SetParent() + .SetGroupName("OFSwitch13"); return tid; + // clang-format on } bool @@ -116,9 +119,9 @@ GtpTunnelApp::RecvFromTunnelSocket(Ptr socket) // and the source address we set here using the physical device. AddHeader(packet, Mac48Address::ConvertFrom(m_physicalDev->GetAddress())); - // Send the packet to the OpenFlow switch over the logical port. - // Don't worry about source and destination addresses becasu they are note - // used by the receive method. + // Send the packet to the OpenFlow switch over the logical port. Don't worry + // about source and destination addresses because they are note used by the + // receive method. m_logicalPort->Receive(packet, Ipv4L3Protocol::PROT_NUMBER, Mac48Address(), @@ -163,8 +166,9 @@ GtpTunnelApp::AddHeader(Ptr packet, NS_LOG_FUNCTION(this << packet << source << dest << protocolNo); // All Ethernet frames must carry a minimum payload of 46 bytes. We need to - // pad out if we don't have enough bytes. These must be real bytes since they - // will be written to pcap files and compared in regression trace files. + // pad out if we don't have enough bytes. These must be real bytes since + // they will be written to pcap files and compared in regression trace + // files. if (packet->GetSize() < 46) { uint8_t buffer[46]; diff --git a/examples/ofswitch13-logical-port/gtp-tunnel-app.h b/examples/ofswitch13-logical-port/gtp-tunnel-app.h index 5206970..03fc10b 100644 --- a/examples/ofswitch13-logical-port/gtp-tunnel-app.h +++ b/examples/ofswitch13-logical-port/gtp-tunnel-app.h @@ -65,8 +65,8 @@ class GtpTunnelApp : public Application * Method to be assigned to the send callback of the VirtualNetDevice * implementing the OpenFlow logical port. It is called when the OpenFlow * switch sends a packet out over the logical port. The logical port - * callbacks here, and we must encapsulate the packet withing GTP and forward - * it to the UDP tunnel socket. + * callbacks here, and we must encapsulate the packet withing GTP and + * forward it to the UDP tunnel socket. * \param packet The packet received from the logical port. * \param source Ethernet source address. * \param dest Ethernet destination address. @@ -79,9 +79,9 @@ class GtpTunnelApp : public Application uint16_t protocolNo); /** - * Method to be assigned to the receive callback of the UDP tunnel socket. It - * is called when the tunnel socket receives a packet, and must forward the - * packet to the logical port. + * Method to be assigned to the receive callback of the UDP tunnel socket. + * It is called when the tunnel socket receives a packet, and must forward + * the packet to the logical port. * \param socket Pointer to the tunnel socket. */ void RecvFromTunnelSocket(Ptr socket); diff --git a/examples/ofswitch13-logical-port/main.cc b/examples/ofswitch13-logical-port/main.cc index 0df2837..95c1684 100644 --- a/examples/ofswitch13-logical-port/main.cc +++ b/examples/ofswitch13-logical-port/main.cc @@ -163,9 +163,9 @@ main(int argc, char* argv[]) hostStaticRouting->AddNetworkRouteTo(ipDomain1, mask24, sw1GatewayIp, 1); // Connect switch 0 to switch 1. These CSMA devices will not be added as - // switch ports. Instead, each one will be configured as standard ns-3 device - // (with IP address and an UDP socket binded to it). They will be used to - // implement the UDP/IP tunneling process. The GtpTunnelApp application + // switch ports. Instead, each one will be configured as standard ns-3 + // device (with IP address and an UDP socket bound to it). They will be used + // to implement the UDP/IP tunneling process. The GtpTunnelApp application // running on top of the UDP socket will be in charge of adding and removing // the GTP headers, and forwarding the packets to a VirtualNetDevice device // on the same node. This VirtualNetDevice will be configured as switch port @@ -214,7 +214,7 @@ main(int argc, char* argv[]) ApplicationContainer pingApps = pingHelper.Install(hosts.Get(0)); pingApps.Start(Seconds(1)); - // Enable datapath stats and pcap traces at hosts, switch(es), and controller(s) + // Enable datapath stats and pcap traces at hosts, switches, and controllers if (trace) { of13Helper->EnableOpenFlowPcap("openflow"); diff --git a/examples/ofswitch13-logical-port/tunnel-controller.cc b/examples/ofswitch13-logical-port/tunnel-controller.cc index 1a778ff..5bbac8c 100644 --- a/examples/ofswitch13-logical-port/tunnel-controller.cc +++ b/examples/ofswitch13-logical-port/tunnel-controller.cc @@ -99,9 +99,7 @@ TunnelController::HandshakeSuccessful(Ptr swtch) uint64_t swDpId = swtch->GetDpId(); // Send ARP requests to controller. - DpctlExecute(swDpId, - "flow-mod cmd=add,table=0,prio=16 eth_type=0x0806 " - "apply:output=ctrl"); + DpctlExecute(swDpId, "flow-mod cmd=add,table=0,prio=16 eth_type=0x0806 apply:output=ctrl"); // Table miss entry. DpctlExecute(swDpId, "flow-mod cmd=add,table=0,prio=0 apply:output=ctrl"); @@ -132,10 +130,10 @@ TunnelController::HandlePacketIn(struct ofl_msg_packet_in* msg, if (inPort == 1) { - // IP packets entering the switch from the physical port 1 are coming - // from the host node. In this case, identify and set TEID and tunnel - // endpoint IPv4 address into tunnel metadata, and output the packet - // on the logical port 2. + // IP packets entering the switch from the physical port 1 are + // coming from the host node. In this case, identify and set TEID + // and tunnel endpoint IPv4 address into tunnel metadata, and output + // the packet on the logical port 2. Ipv4Address dstAddr = GetTunnelEndpoint(swDpId, 2); uint64_t tunnelId = static_cast(dstAddr.Get()) << 32; tunnelId |= 0xFFFF; @@ -155,13 +153,14 @@ TunnelController::HandlePacketIn(struct ofl_msg_packet_in* msg, else if (inPort == 2) { // IP packets entering the switch from the logical port have already - // been de-encapsulated by the logical port operation, and the tunnel - // id must match the arbitrary value 0xFFFF defined set above. Theses - // packets must be forwarded to the host on the physical port 1. In - // this case, the OpenFlow switch is acting as a router, and we need - // to set the host destination MAC addresses. Note that the packet - // leaving the OpenFlow pipeline will not be sent to the IP layer, so - // no ARP resolution is available and we need to do it manually here. + // been de-encapsulated by the logical port operation, and the + // tunnel id must match the arbitrary value 0xFFFF defined set + // above. Theses packets must be forwarded to the host on the + // physical port 1. In this case, the OpenFlow switch is acting as a + // router, and we need to set the host destination MAC addresses. + // Note that the packet leaving the OpenFlow pipeline will not be + // sent to the IP layer, so no ARP resolution is available and we + // need to do it manually here. Ipv4Address dstIp = ExtractIpv4Address(OXM_OF_IPV4_DST, (struct ofl_match*)msg->match); Mac48Address dstMac = GetArpEntry(dstIp); diff --git a/examples/ofswitch13-multiple-controllers.cc b/examples/ofswitch13-multiple-controllers.cc index 7683e13..aeff24b 100644 --- a/examples/ofswitch13-multiple-controllers.cc +++ b/examples/ofswitch13-multiple-controllers.cc @@ -113,10 +113,10 @@ main(int argc, char* argv[]) internet.Install(hosts); // Set IPv4 host addresses - Ipv4AddressHelper ipv4helpr; + Ipv4AddressHelper ipv4Helper; Ipv4InterfaceContainer hostIpIfaces; - ipv4helpr.SetBase("10.1.1.0", "255.255.255.0"); - hostIpIfaces = ipv4helpr.Assign(hostDevices); + ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); + hostIpIfaces = ipv4Helper.Assign(hostDevices); // Configure ping application between hosts PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); diff --git a/examples/ofswitch13-multiple-domains.cc b/examples/ofswitch13-multiple-domains.cc index b3f4217..6a09bed 100644 --- a/examples/ofswitch13-multiple-domains.cc +++ b/examples/ofswitch13-multiple-domains.cc @@ -127,10 +127,10 @@ main(int argc, char* argv[]) internet.Install(hosts); // Set IPv4 host addresses - Ipv4AddressHelper ipv4helpr; + Ipv4AddressHelper ipv4Helper; Ipv4InterfaceContainer hostIpIfaces; - ipv4helpr.SetBase("10.1.1.0", "255.255.255.0"); - hostIpIfaces = ipv4helpr.Assign(hostDevices); + ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); + hostIpIfaces = ipv4Helper.Assign(hostDevices); // Configure ping application between hosts PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); diff --git a/examples/ofswitch13-qos-controller/images/client.png b/examples/ofswitch13-qos-controller/images/client.png deleted file mode 100644 index d4d1fda..0000000 Binary files a/examples/ofswitch13-qos-controller/images/client.png and /dev/null differ diff --git a/examples/ofswitch13-qos-controller/images/controller.png b/examples/ofswitch13-qos-controller/images/controller.png deleted file mode 100644 index b6bf98c..0000000 Binary files a/examples/ofswitch13-qos-controller/images/controller.png and /dev/null differ diff --git a/examples/ofswitch13-qos-controller/images/server.png b/examples/ofswitch13-qos-controller/images/server.png deleted file mode 100644 index 4c74d4a..0000000 Binary files a/examples/ofswitch13-qos-controller/images/server.png and /dev/null differ diff --git a/examples/ofswitch13-qos-controller/images/switch.png b/examples/ofswitch13-qos-controller/images/switch.png deleted file mode 100644 index c189813..0000000 Binary files a/examples/ofswitch13-qos-controller/images/switch.png and /dev/null differ diff --git a/examples/ofswitch13-qos-controller/main.cc b/examples/ofswitch13-qos-controller/main.cc index 4b3292f..6f816d1 100644 --- a/examples/ofswitch13-qos-controller/main.cc +++ b/examples/ofswitch13-qos-controller/main.cc @@ -45,8 +45,6 @@ #include #include #include -#include -#include #include #include @@ -107,26 +105,6 @@ main(int argc, char* argv[]) controllerNodes.Create(2); clientNodes.Create(clients); - // Setting node positions for NetAnim support - Ptr listPosAllocator; - listPosAllocator = CreateObject(); - listPosAllocator->Add(Vector(0, 0, 0)); // Server 0 - listPosAllocator->Add(Vector(0, 75, 0)); // Server 1 - listPosAllocator->Add(Vector(50, 50, 0)); // Border switch - listPosAllocator->Add(Vector(100, 50, 0)); // Aggregation switch - listPosAllocator->Add(Vector(150, 50, 0)); // Client switch - listPosAllocator->Add(Vector(75, 25, 0)); // QoS controller - listPosAllocator->Add(Vector(150, 25, 0)); // Learning controller - for (size_t i = 0; i < clients; i++) - { - listPosAllocator->Add(Vector(200, 25 * i, 0)); // Clients - } - - MobilityHelper mobilityHelper; - mobilityHelper.SetMobilityModel("ns3::ConstantPositionMobilityModel"); - mobilityHelper.SetPositionAllocator(listPosAllocator); - mobilityHelper.Install(NodeContainer(serverNodes, switchNodes, controllerNodes, clientNodes)); - // Create device containers NetDeviceContainer serverDevices; NetDeviceContainer clientDevices; @@ -178,7 +156,8 @@ main(int argc, char* argv[]) Ptr qosCtrl = CreateObject(); ofQosHelper->InstallController(controllerNodes.Get(0), qosCtrl); - // Configure OpenFlow learning controller for client switch (#2) into controller node 1 + // Configure OpenFlow learning controller for client switch (#2) into + // controller node 1 Ptr ofLearningHelper = CreateObject(); Ptr learnCtrl = CreateObject(); ofLearningHelper->InstallController(controllerNodes.Get(1), learnCtrl); @@ -198,7 +177,7 @@ main(int argc, char* argv[]) internet.Install(serverNodes); internet.Install(clientNodes); - // Set IPv4 server and client addresses (discarding the first server address) + // Set IPv4 server and client addresses (discarding first server address) Ipv4AddressHelper ipv4switches; Ipv4InterfaceContainer internetIpIfaces; ipv4switches.SetBase("10.1.0.0", "255.255.0.0", "0.0.1.2"); @@ -244,54 +223,6 @@ main(int argc, char* argv[]) csmaHelper.EnablePcap("client", clientDevices); } - // Creating NetAnim output file - AnimationInterface anim("qosctrl-netanim.xml"); - anim.SetStartTime(Seconds(0)); - anim.SetStopTime(Seconds(4)); - - // Set NetAnim node descriptions - anim.UpdateNodeDescription(0, "Server 0"); - anim.UpdateNodeDescription(1, "Server 1"); - anim.UpdateNodeDescription(2, "Border switch"); - anim.UpdateNodeDescription(3, "Aggregation switch"); - anim.UpdateNodeDescription(4, "Client switch"); - anim.UpdateNodeDescription(5, "QoS controller"); - anim.UpdateNodeDescription(6, "Learning controller"); - for (size_t i = 0; i < clients; i++) - { - std::ostringstream desc; - desc << "Client " << i; - anim.UpdateNodeDescription(7 + i, desc.str()); - } - - // Set NetAnim icon images and size - char cwd[1024]; - if (getcwd(cwd, sizeof(cwd)) != nullptr) - { - std::string path = - std::string(cwd) + "/contrib/ofswitch13/examples/ofswitch13-qos-controller/images/"; - uint32_t serverImg = anim.AddResource(path + "server.png"); - uint32_t switchImg = anim.AddResource(path + "switch.png"); - uint32_t controllerImg = anim.AddResource(path + "controller.png"); - uint32_t clientImg = anim.AddResource(path + "client.png"); - - anim.UpdateNodeImage(0, serverImg); - anim.UpdateNodeImage(1, serverImg); - anim.UpdateNodeImage(2, switchImg); - anim.UpdateNodeImage(3, switchImg); - anim.UpdateNodeImage(4, switchImg); - anim.UpdateNodeImage(5, controllerImg); - anim.UpdateNodeImage(6, controllerImg); - for (size_t i = 0; i < clients; i++) - { - anim.UpdateNodeImage(i + 7, clientImg); - } - for (size_t i = 0; i < clients + 7U; i++) - { - anim.UpdateNodeSize(i, 10, 10); - } - } - // Run the simulation Simulator::Stop(Seconds(simTime)); Simulator::Run(); diff --git a/examples/ofswitch13-qos-controller/qos-controller.cc b/examples/ofswitch13-qos-controller/qos-controller.cc index 0eea1da..44d910e 100644 --- a/examples/ofswitch13-qos-controller/qos-controller.cc +++ b/examples/ofswitch13-qos-controller/qos-controller.cc @@ -226,7 +226,7 @@ QosController::ConfigureAggregationSwitch(Ptr swtch) "weight=0,port=any,group=any output=1"); } - // Packets from input ports 1 and 2 are redirecte to port 3 + // Packets from input ports 1 and 2 are redirected to port 3 DpctlExecute(swDpId, "flow-mod cmd=add,table=0,prio=500 " "in_port=1 write:output=3"); diff --git a/examples/ofswitch13-qos-controller/qos-controller.h b/examples/ofswitch13-qos-controller/qos-controller.h index d3ceeb8..c04acd9 100644 --- a/examples/ofswitch13-qos-controller/qos-controller.h +++ b/examples/ofswitch13-qos-controller/qos-controller.h @@ -140,7 +140,7 @@ class QosController : public OFSwitch13Controller Address m_serverIpAddress; //!< Virtual server IP address uint16_t m_serverTcpPort; //!< Virtual server TCP port Address m_serverMacAddress; //!< Border switch MAC address - bool m_meterEnable; //!< Enable per-flow mettering + bool m_meterEnable; //!< Enable per-flow metering DataRate m_meterRate; //!< Per-flow meter rate bool m_linkAggregation; //!< Enable link aggregation diff --git a/examples/ofswitch13-single-domain.cc b/examples/ofswitch13-single-domain.cc index 6c99131..63d70ce 100644 --- a/examples/ofswitch13-single-domain.cc +++ b/examples/ofswitch13-single-domain.cc @@ -124,10 +124,10 @@ main(int argc, char* argv[]) internet.Install(hosts); // Set IPv4 host addresses - Ipv4AddressHelper ipv4helpr; + Ipv4AddressHelper ipv4Helper; Ipv4InterfaceContainer hostIpIfaces; - ipv4helpr.SetBase("10.1.1.0", "255.255.255.0"); - hostIpIfaces = ipv4helpr.Assign(hostDevices); + ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); + hostIpIfaces = ipv4Helper.Assign(hostDevices); // Configure ping application between hosts PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); diff --git a/helper/ofswitch13-device-container.cc b/helper/ofswitch13-device-container.cc index 6b89190..3eb768e 100644 --- a/helper/ofswitch13-device-container.cc +++ b/helper/ofswitch13-device-container.cc @@ -39,9 +39,8 @@ OFSwitch13DeviceContainer::OFSwitch13DeviceContainer(std::string devName) m_devices.emplace_back(dev); } -OFSwitch13DeviceContainer::OFSwitch13DeviceContainer( - const OFSwitch13DeviceContainer& a, - const OFSwitch13DeviceContainer& b) +OFSwitch13DeviceContainer::OFSwitch13DeviceContainer(const OFSwitch13DeviceContainer& a, + const OFSwitch13DeviceContainer& b) { *this = a; Add(b); diff --git a/helper/ofswitch13-device-container.h b/helper/ofswitch13-device-container.h index 9e97327..f049ad3 100644 --- a/helper/ofswitch13-device-container.h +++ b/helper/ofswitch13-device-container.h @@ -35,11 +35,10 @@ namespace ns3 * Typically OpenFlow Devices are aggregated to nodes using the * OFSwitch13Helper. The helper InstallSwitch* methods takes a NodeContainer * which holds some number of Ptr. For each of the Nodes in the - * NodeContainer the helper will instantiate an OpenFlow device and aggregate - * it to the node. For each of the devices, the helper also adds the device - * into a Container for later use by the caller. This is that container used to - * hold the Ptr which are instantiated by the device - * helper. + * NodeContainer the helper will instantiate an OpenFlow device and aggregate it + * to the node. For each of the devices, the helper also adds the device into a + * Container for later use by the caller. This is that container used to hold + * the Ptr which are instantiated by the device helper. */ class OFSwitch13DeviceContainer { @@ -55,7 +54,6 @@ class OFSwitch13DeviceContainer /** * Create a OFSwitch13DeviceContainer with exactly one device that has * previously been instantiated. - * * \param dev An OpenFlow device to add to the container. */ OFSwitch13DeviceContainer(Ptr dev); @@ -65,7 +63,6 @@ class OFSwitch13DeviceContainer * OFSwitch13DeviceContainer with exactly one device which has been * previously instantiated and assigned a name using the Object name * service. This OpenFlow device is specified by its assigned name. - * * \param devName The name of the device to add to the container. */ OFSwitch13DeviceContainer(std::string devName); @@ -73,7 +70,6 @@ class OFSwitch13DeviceContainer /** * Create a device container which is a concatenation of the two input * OFSwitch13DeviceContainers. - * * \note A frequently seen idiom that uses these constructors involves the * implicit conversion by constructor of Ptr. When used, * two Ptr will be passed to this constructor instead of @@ -81,7 +77,6 @@ class OFSwitch13DeviceContainer * that goes through the OFSwitch13DeviceContainer (Ptr * dev) constructor above. Using this conversion one may provide optionally * provide arguments of Ptr to these constructors. - * * \param a A device container * \param b Another device container * @@ -92,63 +87,54 @@ class OFSwitch13DeviceContainer /** * \brief Get an iterator which refers to the first OpenFlow device in the * container. - * * OpenFlow devices can be retrieved from the container in two ways. First, * directly by an index into the container, and second, using an iterator. * This method is used in the iterator method and is typically used in a * for-loop to run through the devices. - * * \code * OFSwitch13DeviceContainer::Iterator i; - * for (i = container.Begin (); i != container.End (); ++i) - * { - * (*i)->method (); // some OFSwitch13Device method - * } + * for (i = container.Begin(); i != container.End(); ++i) + * { + * (*i)->method(); // some OFSwitch13Device method + * } * \endcode - * * \returns an iterator which refers to the first device in the container. */ Iterator Begin() const; /** - * \brief Get an iterator which indicates past-the-last OpenFlow device in + * \brief Get an iterator which indicates past-the-last OpenFlow device in * the container. - * * OpenFlow devices can be retrieved from the container in two ways. First, * directly by an index into the container, and second, using an iterator. * This method is used in the iterator method and is typically used in a * for-loop to run through the devices - * * \code * OFSwitch13DeviceContainer::Iterator i; - * for (i = container.Begin (); i != container.End (); ++i) - * { - * (*i)->method (); // some OFSwitch13Device method - * } + * for (i = container.Begin(); i != container.End(); ++i) + * { + * (*i)->method(); // some OFSwitch13Device method + * } * \endcode - * * \returns an iterator which indicates an ending condition for a loop. */ Iterator End() const; /** * \brief Get the number of Ptr stored in this container. - * * OpenFlow devices can be retrieved from the container in two ways. First, * directly by an index into the container, and second, using an iterator. * This method is used in the direct method and is typically used to * define an ending condition in a for-loop that runs through the stored * devices - * * \code - * uint32_t nDevices = container.GetN (); + * uint32_t nDevices = container.GetN(); * for (uint32_t i = 0 i < nDevices; ++i) - * { - * Ptr p = container.Get (i); - * p->method (); // some OFSwitch13Device method - * } + * { + * Ptr p = container.Get(i); + * p->method(); // some OFSwitch13Device method + * } * \endcode - * * \returns the number of Ptr stored in this container. */ uint32_t GetN() const; @@ -156,21 +142,18 @@ class OFSwitch13DeviceContainer /** * \brief Get the Ptr stored in this container at a given * index. - * * OpenFlow devices can be retrieved from the container in two ways.First, * directly by an index into the container, and second, using an iterator. * This method is used in the direct method and is used to retrieve the * indexed Ptr. - * * \code - * uint32_t nDevices = container.GetN (); + * uint32_t nDevices = container.GetN(); * for (uint32_t i = 0 i < nDevices; ++i) - * { - * Ptr p = container.Get (i); - * p->method (); // some OFSwitch13Device method - * } + * { + * Ptr p = container.Get(i); + * p->method(); // some OFSwitch13Device method + * } * \endcode - * * \param i the index of the requested device pointer. * \returns the requested device pointer. */ @@ -179,14 +162,12 @@ class OFSwitch13DeviceContainer /** * \brief Append the contents of another OFSwitch13DeviceContainer to the * end of this container. - * * \param other The OFSwitch13DeviceContainer to append. */ void Add(OFSwitch13DeviceContainer other); /** * \brief Append a single Ptr to this container. - * * \param device The Ptr to append. */ void Add(Ptr device); @@ -194,7 +175,6 @@ class OFSwitch13DeviceContainer /** * \brief Append to this container the single Ptr referred * to via its object name service registered name. - * * \param deviceName The name of the OFSwitch13Device object to add to the * container. */ diff --git a/helper/ofswitch13-external-helper.cc b/helper/ofswitch13-external-helper.cc index de31ab2..ce7e1db 100644 --- a/helper/ofswitch13-external-helper.cc +++ b/helper/ofswitch13-external-helper.cc @@ -50,12 +50,11 @@ OFSwitch13ExternalHelper::GetTypeId() .SetParent() .SetGroupName("OFSwitch13") .AddConstructor() - .AddAttribute( - "Port", - "The port number where controller will be available.", - UintegerValue(6653), - MakeUintegerAccessor(&OFSwitch13ExternalHelper::m_controlPort), - MakeUintegerChecker()); + .AddAttribute("Port", + "The port number where controller will be available.", + UintegerValue(6653), + MakeUintegerAccessor(&OFSwitch13ExternalHelper::m_controlPort), + MakeUintegerChecker()); return tid; } @@ -66,8 +65,7 @@ OFSwitch13ExternalHelper::SetChannelType(ChannelType type) // Check for valid channel type for this helper. NS_ABORT_MSG_IF(type != OFSwitch13Helper::SINGLECSMA, - "Invalid channel " - "type for OFSwitch13ExternalHelper (use SingleCsma)."); + "Invalid channel type for OFSwitch13ExternalHelper (use SingleCsma)."); OFSwitch13Helper::SetChannelType(type); } @@ -95,8 +93,7 @@ OFSwitch13ExternalHelper::CreateOpenFlowChannels() switch (m_channelType) { case OFSwitch13ExternalHelper::SINGLECSMA: { - NS_LOG_INFO("Attach all switches and controllers to the same " - "CSMA network."); + NS_LOG_INFO("Attach all switches and controllers to the same CSMA network."); // Connecting all switches to the common channel. NetDeviceContainer switchDevices; @@ -106,15 +103,11 @@ OFSwitch13ExternalHelper::CreateOpenFlowChannels() // Start the connections between controller and switches. OFSwitch13DeviceContainer::Iterator ofDev; - for (ofDev = m_openFlowDevs.Begin(); ofDev != m_openFlowDevs.End(); - ofDev++) + for (ofDev = m_openFlowDevs.Begin(); ofDev != m_openFlowDevs.End(); ofDev++) { - NS_LOG_INFO("Connect switch " << (*ofDev)->GetDatapathId() - << " to controller " << addr.GetIpv4() - << " port " << addr.GetPort()); - Simulator::ScheduleNow(&OFSwitch13Device::StartControllerConnection, - *ofDev, - addr); + NS_LOG_INFO("Connect switch " << (*ofDev)->GetDatapathId() << " to controller " + << addr.GetIpv4() << " port " << addr.GetPort()); + Simulator::ScheduleNow(&OFSwitch13Device::StartControllerConnection, *ofDev, addr); } m_ipv4helper.NewNetwork(); break; @@ -133,8 +126,7 @@ OFSwitch13ExternalHelper::InstallExternalController(Ptr cNode) NS_LOG_FUNCTION(this << cNode); NS_LOG_INFO("Installing OpenFlow controller on node " << cNode->GetId()); - NS_ABORT_MSG_IF(m_blocked || m_controlDevs.GetN() != 0, - "OpenFlow controller/channels already configured."); + NS_ABORT_MSG_IF(m_blocked || m_controlDevs.GetN() != 0, "OpenFlow channel already configured."); // Install the TCP/IP stack into controller node. if (!cNode->GetObject()) diff --git a/helper/ofswitch13-external-helper.h b/helper/ofswitch13-external-helper.h index 64e49af..1260852 100644 --- a/helper/ofswitch13-external-helper.h +++ b/helper/ofswitch13-external-helper.h @@ -62,7 +62,6 @@ class OFSwitch13ExternalHelper : public OFSwitch13Helper * the local machine over a TapBridge device. It installs the TCP/IP stack * into controller node, attach it to the common CSMA channel and configure * IP address for it. - * * \param cNode The node to configure as the controller. * \return The network device to bind to the TapBridge. */ diff --git a/helper/ofswitch13-helper.cc b/helper/ofswitch13-helper.cc index d523ea7..ecc0e14 100644 --- a/helper/ofswitch13-helper.cc +++ b/helper/ofswitch13-helper.cc @@ -31,8 +31,7 @@ namespace ns3 NS_LOG_COMPONENT_DEFINE("OFSwitch13Helper"); NS_OBJECT_ENSURE_REGISTERED(OFSwitch13Helper); -Ipv4AddressHelper OFSwitch13Helper::m_ipv4helper = - Ipv4AddressHelper("10.100.0.0", "255.255.255.0"); +Ipv4AddressHelper OFSwitch13Helper::m_ipv4helper = Ipv4AddressHelper("10.100.0.0", "255.255.255.0"); class OFSwitch13Controller; @@ -57,24 +56,22 @@ OFSwitch13Helper::GetTypeId() TypeId("ns3::OFSwitch13Helper") .SetParent() .SetGroupName("OFSwitch13") - .AddAttribute( - "ChannelDataRate", - "The data rate to be used for the OpenFlow channel.", - DataRateValue(DataRate("10Gb/s")), - MakeDataRateAccessor(&OFSwitch13Helper::SetChannelDataRate), - MakeDataRateChecker()) - .AddAttribute( - "ChannelType", - "The configuration used to create the OpenFlow channel", - TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, - EnumValue(OFSwitch13Helper::SINGLECSMA), - MakeEnumAccessor(&OFSwitch13Helper::SetChannelType), - MakeEnumChecker(OFSwitch13Helper::SINGLECSMA, - "SingleCsma", - OFSwitch13Helper::DEDICATEDCSMA, - "DedicatedCsma", - OFSwitch13Helper::DEDICATEDP2P, - "DedicatedP2p")); + .AddAttribute("ChannelDataRate", + "The data rate to be used for the OpenFlow channel.", + DataRateValue(DataRate("10Gb/s")), + MakeDataRateAccessor(&OFSwitch13Helper::SetChannelDataRate), + MakeDataRateChecker()) + .AddAttribute("ChannelType", + "The configuration used to create the OpenFlow channel", + TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, + EnumValue(OFSwitch13Helper::SINGLECSMA), + MakeEnumAccessor(&OFSwitch13Helper::SetChannelType), + MakeEnumChecker(OFSwitch13Helper::SINGLECSMA, + "SingleCsma", + OFSwitch13Helper::DEDICATEDCSMA, + "DedicatedCsma", + OFSwitch13Helper::DEDICATEDP2P, + "DedicatedP2p")); return tid; } @@ -91,7 +88,7 @@ OFSwitch13Helper::SetChannelType(ChannelType type) { NS_LOG_FUNCTION(this << type); - // Set the channel type and address, which will select proper netowrk mask. + // Set the channel type and address, which will select proper network mask. m_channelType = type; } @@ -167,7 +164,7 @@ OFSwitch13Helper::EnableDatapathStats(std::string prefix, bool useNodeNames) const std::string extension = ".log"; // Iterate over the container and for each OpenFlow devices create a stats - // calculator to monitor datapath statistcs. + // calculator to monitor datapath statistics. OFSwitch13DeviceContainer::Iterator it; for (it = m_openFlowDevs.Begin(); it != m_openFlowDevs.End(); it++) { @@ -256,9 +253,7 @@ OFSwitch13Helper::InstallSwitch(NodeContainer& swNodes) } void -OFSwitch13Helper::SetAddressBase(Ipv4Address network, - Ipv4Mask mask, - Ipv4Address base) +OFSwitch13Helper::SetAddressBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base) { NS_LOG_FUNCTION_NOARGS(); diff --git a/helper/ofswitch13-helper.h b/helper/ofswitch13-helper.h index ede92c9..48480eb 100644 --- a/helper/ofswitch13-helper.h +++ b/helper/ofswitch13-helper.h @@ -55,19 +55,19 @@ class OFSwitch13LearningController; * * By default, the connections between switches and controllers are created * using a single shared out-of-band CSMA channel, with IP addresses assigned - * using a /24 network mask. Users can modify this configuration by changing - * the ChannelType attribute at instantiation time. Dedicated out-of-band + * using a /24 network mask. Users can modify this configuration by changing the + * ChannelType attribute at instantiation time. Dedicated out-of-band * connections over CSMA or Point-to-Point channels are also available, using a * /30 network mask for IP allocation. * * Please note that this base helper class was designed to configure a single - * OpenFlow network domain. All switches will be connected to all controllers - * on the same domain. If you want to configure separated OpenFlow domains on - * your network topology (with their individual switches and controllers) so - * you may need to use a different instance of the derived helper class for - * each domain. In this case, don't forget to use the SetAddressBase () - * method to change the IP network address of the other helper instances, in - * order to avoid IP conflicts. + * OpenFlow network domain. All switches will be connected to all controllers on + * the same domain. If you want to configure separated OpenFlow domains on your + * network topology (with their individual switches and controllers) so you may + * need to use a different instance of the derived helper class for each domain. + * In this case, don't forget to use the SetAddressBase() method to change the + * IP network address of the other helper instances, in order to avoid IP + * conflicts. */ class OFSwitch13Helper : public Object { @@ -94,7 +94,6 @@ class OFSwitch13Helper : public Object /** * Set an attribute on each OpenFlow device created by this helper. - * * \param n1 the name of the attribute to set. * \param v1 the value of the attribute to set. */ @@ -103,7 +102,6 @@ class OFSwitch13Helper : public Object /** * Set the OpenFlow channel type used to create the connections between * switches and controllers. - * * \param type The ChannelType to use. */ virtual void SetChannelType(ChannelType type); @@ -111,27 +109,21 @@ class OFSwitch13Helper : public Object /** * Set the OpenFlow channel data rate used to create the connections between * switches and controllers. - * * \param rate The channel data rate to use. */ virtual void SetChannelDataRate(DataRate rate); /** - * Enable pacp traces at OpenFlow channel between controller and switches. - * + * Enable pcap traces at OpenFlow channel between controller and switches. * \attention Call this method only after configuring the OpenFlow channels. - * * \param prefix Filename prefix to use for pcap files. * \param promiscuous If true, enable promisc trace. */ - void EnableOpenFlowPcap(std::string prefix = "ofchannel", - bool promiscuous = true); + void EnableOpenFlowPcap(std::string prefix = "ofchannel", bool promiscuous = true); /** * Enable ASCII traces at OpenFlow channel between controller and switches. - * * \attention Call this method only after configuring the OpenFlow channels. - * * \param prefix Filename prefix to use for ascii files. */ void EnableOpenFlowAscii(std::string prefix = "ofchannel"); @@ -139,34 +131,28 @@ class OFSwitch13Helper : public Object /** * Enable OpenFlow datapath statistics at OpenFlow switch devices configured * by this helper. This method will create an OFSwitch13StatsCalculator for - * each switch device, dumping statistcs to output files. - * + * each switch device, dumping statistics to output files. * \attention Call this method only after configuring the OpenFlow channels. - * * \param prefix Filename prefix to use for stats files. * \param useNodeNames Use node names instead of datapath id. */ - void EnableDatapathStats(std::string prefix = "datapath", - bool useNodeNames = false); + void EnableDatapathStats(std::string prefix = "datapath", bool useNodeNames = false); /** * This method creates an OpenFlow device and aggregates it to the switch * node. It also attaches the given devices as physical ports on the switch. * If no devices are given, the switch will be configured without ports. In * this case, don't forget to add ports to it later, or it will do nothing. - * * \param swNode The switch node where to install the OpenFlow device. * \param ports Container of devices to be added as physical switch ports. * \return The OpenFlow device created. */ - Ptr InstallSwitch(Ptr swNode, - NetDeviceContainer& swPorts); + Ptr InstallSwitch(Ptr swNode, NetDeviceContainer& swPorts); /** * This method creates an OpenFlow device and aggregates it to the switch * node. The switch configured by this method will have no switch ports. * Don't forget to add ports do it later, or it will do nothing. - * * \param swNode The switch node where to install the OpenFlow device. * \return The OpenFlow device created. */ @@ -176,7 +162,6 @@ class OFSwitch13Helper : public Object * This method creates and aggregates an OpenFlow device to each switch node * in the container. Switches configured by this method will have no switch * ports. Don't forget to add ports do them later, or they will do nothing. - * * \param swNodes The switch nodes where to install the OpenFlow devices. * \return A container holding all the OpenFlow devices created. */ @@ -193,8 +178,7 @@ class OFSwitch13Helper : public Object /** * Set the IP network base address, used to assign IP addresses to switches - * and controllers during the CreateOpenFlowChannels () procedure. - * + * and controllers during the CreateOpenFlowChannels() procedure. * \param network The Ipv4Address containing the initial network number to * use during allocation. * \param mask The Ipv4Mask containing one bits in each bit position of the @@ -202,20 +186,16 @@ class OFSwitch13Helper : public Object * \param base An optional Ipv4Address containing the initial address used * for IP address allocation. */ - static void SetAddressBase(Ipv4Address network, - Ipv4Mask mask, - Ipv4Address base = "0.0.0.1"); + static void SetAddressBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base = "0.0.0.1"); /** * Enable OpenFlow datapath logs at all OpenFlow switch devices on the * simulation. This method will enable vlog system at debug level on the * BOFUSS library, dumping messages to output file. - * * \param prefix Filename prefix to use for log file. * \param explicitFilename Treat the prefix as an explicit filename if true. */ - static void EnableDatapathLogs(std::string prefix = "", - bool explicitFilename = false); + static void EnableDatapathLogs(std::string prefix = "", bool explicitFilename = false); protected: /** Destructor implementation. */ diff --git a/helper/ofswitch13-internal-helper.cc b/helper/ofswitch13-internal-helper.cc index 6782211..6c08c1a 100644 --- a/helper/ofswitch13-internal-helper.cc +++ b/helper/ofswitch13-internal-helper.cc @@ -66,13 +66,11 @@ OFSwitch13InternalHelper::CreateOpenFlowChannels() switch (m_channelType) { case OFSwitch13InternalHelper::SINGLECSMA: { - NS_LOG_INFO("Attach all switches and controllers to the same " - "CSMA network."); + NS_LOG_INFO("Attach all switches and controllers to the same CSMA network."); // Create the common channel for all switches and controllers. - Ptr csmaChannel = CreateObjectWithAttributes( - "DataRate", - DataRateValue(m_channelDataRate)); + Ptr csmaChannel = + CreateObjectWithAttributes("DataRate", DataRateValue(m_channelDataRate)); // Connecting all switches and controllers to the common channel. NetDeviceContainer switchDevices; @@ -87,20 +85,14 @@ OFSwitch13InternalHelper::CreateOpenFlowChannels() for (uint32_t ctIdx = 0; ctIdx < controllerAddrs.GetN(); ctIdx++) { m_controlApps.Get(ctIdx)->GetAttribute("Port", portValue); - InetSocketAddress addr(controllerAddrs.GetAddress(ctIdx), - portValue.Get()); + InetSocketAddress addr(controllerAddrs.GetAddress(ctIdx), portValue.Get()); OFSwitch13DeviceContainer::Iterator ofDev; - for (ofDev = m_openFlowDevs.Begin(); ofDev != m_openFlowDevs.End(); - ofDev++) + for (ofDev = m_openFlowDevs.Begin(); ofDev != m_openFlowDevs.End(); ofDev++) { - NS_LOG_INFO("Connect switch " - << (*ofDev)->GetDatapathId() << " to controller " - << addr.GetIpv4() << " port " << addr.GetPort()); - Simulator::ScheduleNow( - &OFSwitch13Device::StartControllerConnection, - *ofDev, - addr); + NS_LOG_INFO("Connect switch " << (*ofDev)->GetDatapathId() << " to controller " + << addr.GetIpv4() << " port " << addr.GetPort()); + Simulator::ScheduleNow(&OFSwitch13Device::StartControllerConnection, *ofDev, addr); } } m_ipv4helper.NewNetwork(); @@ -109,25 +101,19 @@ OFSwitch13InternalHelper::CreateOpenFlowChannels() case OFSwitch13InternalHelper::DEDICATEDCSMA: case OFSwitch13InternalHelper::DEDICATEDP2P: { // Setting channel/device data rates. - m_p2pHelper.SetDeviceAttribute("DataRate", - DataRateValue(m_channelDataRate)); - m_csmaHelper.SetChannelAttribute("DataRate", - DataRateValue(m_channelDataRate)); + m_p2pHelper.SetDeviceAttribute("DataRate", DataRateValue(m_channelDataRate)); + m_csmaHelper.SetChannelAttribute("DataRate", DataRateValue(m_channelDataRate)); // To avoid IP datagram fragmentation, we are configuring the OpenFlow // channel devices with a very large MTU value. The TCP sockets used to - // send packets to theses devices are also configured to use a large + // send packets to these devices are also configured to use a large // segment size at OFSwitch13Controller and OFSwitch13Device. m_csmaHelper.SetDeviceAttribute("Mtu", UintegerValue(9000)); m_p2pHelper.SetDeviceAttribute("Mtu", UintegerValue(9000)); // Using large queues on devices to avoid losing packets. - m_csmaHelper.SetQueue("ns3::DropTailQueue", - "MaxSize", - StringValue("65536p")); - m_p2pHelper.SetQueue("ns3::DropTailQueue", - "MaxSize", - StringValue("65536p")); + m_csmaHelper.SetQueue("ns3::DropTailQueue", "MaxSize", StringValue("65536p")); + m_p2pHelper.SetQueue("ns3::DropTailQueue", "MaxSize", StringValue("65536p")); // Create individual channels for each pair switch/controller. UintegerValue portValue; @@ -143,21 +129,15 @@ OFSwitch13InternalHelper::CreateOpenFlowChannels() NetDeviceContainer pairDevs = Connect(ctNode, swNode); m_controlDevs.Add(pairDevs.Get(0)); - Ipv4InterfaceContainer pairIfaces = - m_ipv4helper.Assign(pairDevs); + Ipv4InterfaceContainer pairIfaces = m_ipv4helper.Assign(pairDevs); // Start this single connection between switch and controller. m_controlApps.Get(ctIdx)->GetAttribute("Port", portValue); - InetSocketAddress addr(pairIfaces.GetAddress(0), - portValue.Get()); - - NS_LOG_INFO("Connect switch " - << ofDev->GetDatapathId() << " to controller " - << addr.GetIpv4() << " port " << addr.GetPort()); - Simulator::ScheduleNow( - &OFSwitch13Device::StartControllerConnection, - ofDev, - addr); + InetSocketAddress addr(pairIfaces.GetAddress(0), portValue.Get()); + + NS_LOG_INFO("Connect switch " << ofDev->GetDatapathId() << " to controller " + << addr.GetIpv4() << " port " << addr.GetPort()); + Simulator::ScheduleNow(&OFSwitch13Device::StartControllerConnection, ofDev, addr); m_ipv4helper.NewNetwork(); } } @@ -170,9 +150,7 @@ OFSwitch13InternalHelper::CreateOpenFlowChannels() } Ptr -OFSwitch13InternalHelper::InstallController( - Ptr cNode, - Ptr controller) +OFSwitch13InternalHelper::InstallController(Ptr cNode, Ptr controller) { NS_LOG_FUNCTION(this << cNode << controller); diff --git a/helper/ofswitch13-internal-helper.h b/helper/ofswitch13-internal-helper.h index 36895cd..7f38d95 100644 --- a/helper/ofswitch13-internal-helper.h +++ b/helper/ofswitch13-internal-helper.h @@ -58,15 +58,13 @@ class OFSwitch13InternalHelper : public OFSwitch13Helper * This method installs the given controller application into the given * controller node. If no application is given, a new (default) learning * controller application is created and installed into controller node. - * * \param cNode The node to configure as controller. * \param controller The controller application to install into cNode * \return The installed controller application. */ Ptr InstallController( Ptr cNode, - Ptr controller = - CreateObject()); + Ptr controller = CreateObject()); protected: /** Destructor implementation. */ @@ -75,7 +73,6 @@ class OFSwitch13InternalHelper : public OFSwitch13Helper /** * Create an individual connection between the switch and the controller * node, using the already configured channel type. - * * \param ctrl The controller node. * \param swtch The switch node. * \return The devices created on both nodes. diff --git a/helper/ofswitch13-stats-calculator.cc b/helper/ofswitch13-stats-calculator.cc index f6e88b3..3443e35 100644 --- a/helper/ofswitch13-stats-calculator.cc +++ b/helper/ofswitch13-stats-calculator.cc @@ -72,37 +72,34 @@ OFSwitch13StatsCalculator::GetTypeId() .SetParent() .SetGroupName("OFSwitch13") .AddConstructor() - .AddAttribute( - "EwmaAlpha", - "The EWMA alpha parameter for averaging statistics.", - DoubleValue(0.2), - MakeDoubleAccessor(&OFSwitch13StatsCalculator::m_alpha), - MakeDoubleChecker(0.0, 1.0)) - .AddAttribute( - "DumpTimeout", - "The interval to update and dump switch statistics.", - TimeValue(Seconds(1)), - MakeTimeAccessor(&OFSwitch13StatsCalculator::m_timeout), - MakeTimeChecker(Seconds(1))) - .AddAttribute( - "OutputFilename", - "Filename for dumping switch statistics.", - TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, - StringValue("ofswitch_stats.log"), - MakeStringAccessor(&OFSwitch13StatsCalculator::m_filename), - MakeStringChecker()) - .AddAttribute( - "FlowTableDetails", - "Dump individual pipeline flow table statistics.", - BooleanValue(false), - MakeBooleanAccessor(&OFSwitch13StatsCalculator::m_details), - MakeBooleanChecker()); + .AddAttribute("EwmaAlpha", + "The EWMA alpha parameter for averaged statistics.", + DoubleValue(0.2), + MakeDoubleAccessor(&OFSwitch13StatsCalculator::m_alpha), + MakeDoubleChecker(0.0, 1.0)) + .AddAttribute("DumpTimeout", + "The interval to update and dump switch statistics.", + TimeValue(Seconds(1)), + MakeTimeAccessor(&OFSwitch13StatsCalculator::m_timeout), + MakeTimeChecker(Seconds(1))) + .AddAttribute("OutputFilename", + "Filename for dumping switch statistics.", + TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, + StringValue("ofswitch_stats.log"), + MakeStringAccessor(&OFSwitch13StatsCalculator::m_filename), + MakeStringChecker()) + .AddAttribute("FlowTableDetails", + "Dump individual pipeline flow table statistics.", + BooleanValue(false), + MakeBooleanAccessor(&OFSwitch13StatsCalculator::m_details), + MakeBooleanChecker()); return tid; } void OFSwitch13StatsCalculator::HookSinks(Ptr device) { + // clang-format off NS_LOG_FUNCTION(this << device); // Save switch device pointer. @@ -138,8 +135,8 @@ OFSwitch13StatsCalculator::HookSinks(Ptr device) { std::string field1 = "T" + to_string(i) + "Entr"; std::string field2 = "T" + to_string(i) + "Usag"; - *m_wrapper->GetStream() - << " " << setw(7) << field1 << " " << setw(7) << field2; + *m_wrapper->GetStream() << " " << setw(7) << field1 + << " " << setw(7) << field2; } } @@ -168,6 +165,7 @@ OFSwitch13StatsCalculator::HookSinks(Ptr device) Ptr(this))); m_ewmaFlowEntries.resize(device->GetNPipelineTables(), 0.0); + // clang-format on } uint32_t @@ -230,9 +228,8 @@ OFSwitch13StatsCalculator::GetAvgCpuUsage() const { return 0; } - return std::round( - static_cast(GetEwmaCpuLoad().GetBitRate()) * 100 / - static_cast(m_device->GetCpuCapacity().GetBitRate())); + return std::round(static_cast(GetEwmaCpuLoad().GetBitRate()) * 100 / + static_cast(m_device->GetCpuCapacity().GetBitRate())); } uint32_t @@ -242,8 +239,7 @@ OFSwitch13StatsCalculator::GetAvgFlowTableUsage(uint8_t tableId) const { return 0; } - return std::round(static_cast(GetEwmaFlowTableEntries(tableId)) * - 100 / + return std::round(static_cast(GetEwmaFlowTableEntries(tableId)) * 100 / static_cast(m_device->GetFlowTableSize(tableId))); } @@ -307,39 +303,38 @@ OFSwitch13StatsCalculator::NotifyConstructionCompleted() m_wrapper = Create(m_filename, std::ios::out); // Scheduling first update and dump. - Simulator::Schedule(m_timeout, - &OFSwitch13StatsCalculator::DumpStatistics, - this); + Simulator::Schedule(m_timeout, &OFSwitch13StatsCalculator::DumpStatistics, this); // Chain up. Object::NotifyConstructionCompleted(); } void -OFSwitch13StatsCalculator::NotifyDatapathTimeout( - Ptr device) +OFSwitch13StatsCalculator::NotifyDatapathTimeout(Ptr device) { + // clang-format off NS_LOG_FUNCTION(this); NS_ASSERT_MSG(m_device == device, "Invalid device pointer."); - m_ewmaBufferEntries = m_alpha * m_device->GetBufferEntries() + - (1 - m_alpha) * m_ewmaBufferEntries; - m_ewmaCpuLoad = m_alpha * m_device->GetCpuLoad().GetBitRate() + - (1 - m_alpha) * m_ewmaCpuLoad; - m_ewmaSumFlowEntries = m_alpha * m_device->GetSumFlowEntries() + - (1 - m_alpha) * m_ewmaSumFlowEntries; - m_ewmaGroupEntries = m_alpha * m_device->GetGroupTableEntries() + - (1 - m_alpha) * m_ewmaGroupEntries; - m_ewmaMeterEntries = m_alpha * m_device->GetMeterTableEntries() + - (1 - m_alpha) * m_ewmaMeterEntries; - m_ewmaPipelineDelay = m_alpha * m_device->GetPipelineDelay().GetDouble() + - (1 - m_alpha) * m_ewmaPipelineDelay; + m_ewmaBufferEntries = + m_alpha * m_device->GetBufferEntries() + (1 - m_alpha) * m_ewmaBufferEntries; + m_ewmaCpuLoad = + m_alpha * m_device->GetCpuLoad().GetBitRate() + (1 - m_alpha) * m_ewmaCpuLoad; + m_ewmaSumFlowEntries = + m_alpha * m_device->GetSumFlowEntries() + (1 - m_alpha) * m_ewmaSumFlowEntries; + m_ewmaGroupEntries = + m_alpha * m_device->GetGroupTableEntries() + (1 - m_alpha) * m_ewmaGroupEntries; + m_ewmaMeterEntries = + m_alpha * m_device->GetMeterTableEntries() + (1 - m_alpha) * m_ewmaMeterEntries; + m_ewmaPipelineDelay = + m_alpha * m_device->GetPipelineDelay().GetDouble() + (1 - m_alpha) * m_ewmaPipelineDelay; for (size_t i = 0; i < m_device->GetNPipelineTables(); i++) { - m_ewmaFlowEntries.at(i) = m_alpha * m_device->GetFlowTableEntries(i) + - (1 - m_alpha) * m_ewmaFlowEntries.at(i); + m_ewmaFlowEntries.at(i) = + m_alpha * m_device->GetFlowTableEntries(i) + (1 - m_alpha) * m_ewmaFlowEntries.at(i); } + // clang-format on } void @@ -351,8 +346,7 @@ OFSwitch13StatsCalculator::NotifyOverloadDrop(Ptr packet) } void -OFSwitch13StatsCalculator::NotifyMeterDrop(Ptr packet, - uint32_t meterId) +OFSwitch13StatsCalculator::NotifyMeterDrop(Ptr packet, uint32_t meterId) { NS_LOG_FUNCTION(this << packet << meterId); @@ -360,8 +354,7 @@ OFSwitch13StatsCalculator::NotifyMeterDrop(Ptr packet, } void -OFSwitch13StatsCalculator::NotifyTableDrop(Ptr packet, - uint8_t tableId) +OFSwitch13StatsCalculator::NotifyTableDrop(Ptr packet, uint8_t tableId) { NS_LOG_FUNCTION(this << packet << +tableId); @@ -398,39 +391,42 @@ OFSwitch13StatsCalculator::DumpStatistics() uint32_t cpuUsage = 0; if (cpuCapy) { - cpuUsage = std::round(static_cast(cpuLoad) * 100 / - static_cast(cpuCapy)); + cpuUsage = std::round(static_cast(cpuLoad) * 100 / static_cast(cpuCapy)); } // Print statistics to file. - *m_wrapper->GetStream() - << " " << setw(8) << Simulator::Now().GetSeconds() << " " << setw(12) - << static_cast(cpuLoad) / 1000 << " " << setw(7) << cpuUsage - << " " << setw(7) << m_packets << " " << setw(7) - << GetEwmaPipelineDelay().GetMicroSeconds() << " " << setw(7) - << m_loadDrops << " " << setw(7) << m_meterDrops << " " << setw(7) - << m_tableDrops << " " << setw(7) << flowMods - m_lastFlowMods << " " - << setw(7) << meterMods - m_lastMeterMods << " " << setw(7) - << groupMods - m_lastGroupMods << " " << setw(7) - << packetsIn - m_lastPacketsIn << " " << setw(7) - << packetsOut - m_lastPacketsOut << " " << setw(7) - << GetEwmaSumFlowEntries() << " " << setw(7) - << GetAvgActFlowTableUsage() << " " << setw(7) - << GetEwmaMeterTableEntries() << " " << setw(7) - << GetAvgMeterTableUsage() << " " << setw(7) - << GetEwmaGroupTableEntries() << " " << setw(7) - << GetAvgGroupTableUsage() << " " << setw(7) << GetEwmaBufferEntries() - << " " << setw(7) << GetAvgBufferUsage(); + // clang-format off + *m_wrapper->GetStream() << " " << setw(8) << Simulator::Now().GetSeconds() + << " " << setw(12) << static_cast(cpuLoad) / 1000 + << " " << setw(7) << cpuUsage + << " " << setw(7) << m_packets + << " " << setw(7) << GetEwmaPipelineDelay().GetMicroSeconds() + << " " << setw(7) << m_loadDrops + << " " << setw(7) << m_meterDrops + << " " << setw(7) << m_tableDrops + << " " << setw(7) << flowMods - m_lastFlowMods + << " " << setw(7) << meterMods - m_lastMeterMods + << " " << setw(7) << groupMods - m_lastGroupMods + << " " << setw(7) << packetsIn - m_lastPacketsIn + << " " << setw(7) << packetsOut - m_lastPacketsOut + << " " << setw(7) << GetEwmaSumFlowEntries() + << " " << setw(7) << GetAvgActFlowTableUsage() + << " " << setw(7) << GetEwmaMeterTableEntries() + << " " << setw(7) << GetAvgMeterTableUsage() + << " " << setw(7) << GetEwmaGroupTableEntries() + << " " << setw(7) << GetAvgGroupTableUsage() + << " " << setw(7) << GetEwmaBufferEntries() + << " " << setw(7) << GetAvgBufferUsage(); if (m_details) { for (size_t i = 0; i < m_device->GetNPipelineTables(); i++) { - *m_wrapper->GetStream() - << " " << setw(7) << GetEwmaFlowTableEntries(i) << " " - << setw(7) << GetAvgFlowTableUsage(i); + *m_wrapper->GetStream() << " " << setw(7) << GetEwmaFlowTableEntries(i) + << " " << setw(7) << GetAvgFlowTableUsage(i); } } + // clang-format on *m_wrapper->GetStream() << std::endl; @@ -448,9 +444,7 @@ OFSwitch13StatsCalculator::DumpStatistics() // Scheduling next update. m_lastUpdate = Simulator::Now(); - Simulator::Schedule(m_timeout, - &OFSwitch13StatsCalculator::DumpStatistics, - this); + Simulator::Schedule(m_timeout, &OFSwitch13StatsCalculator::DumpStatistics, this); } } // Namespace ns3 diff --git a/helper/ofswitch13-stats-calculator.h b/helper/ofswitch13-stats-calculator.h index 0ded199..6c16b08 100644 --- a/helper/ofswitch13-stats-calculator.h +++ b/helper/ofswitch13-stats-calculator.h @@ -72,8 +72,8 @@ class OFSwitch13StatsCalculator : public Object static TypeId GetTypeId(); /** - * Hook switch device trace sources to internal stats calculator trace - * sinks. \param device The OpenFlow switch device to monitor. + * Hook switch device trace sources to stats calculator trace sinks. + * \param device The OpenFlow switch device to monitor. */ void HookSinks(Ptr device); @@ -154,8 +154,8 @@ class OFSwitch13StatsCalculator : public Object void NotifyPipelinePacket(Ptr packet); /** - * Read statistics from switch, update internal counters, - * and dump data into output file. + * Read statistics from switch, update internal counters, and dump data into + * output file. */ void DumpStatistics(); diff --git a/model/ofswitch13-controller.cc b/model/ofswitch13-controller.cc index 89fd00d..651c9e3 100644 --- a/model/ofswitch13-controller.cc +++ b/model/ofswitch13-controller.cc @@ -47,15 +47,14 @@ OFSwitch13Controller::~OFSwitch13Controller() TypeId OFSwitch13Controller::GetTypeId() { - static TypeId tid = - TypeId("ns3::OFSwitch13Controller") - .SetParent() - .SetGroupName("OFSwitch13") - .AddAttribute("Port", - "Port number to listen for incoming packets.", - UintegerValue(6653), - MakeUintegerAccessor(&OFSwitch13Controller::m_port), - MakeUintegerChecker()); + static TypeId tid = TypeId("ns3::OFSwitch13Controller") + .SetParent() + .SetGroupName("OFSwitch13") + .AddAttribute("Port", + "Port number to listen for incoming packets.", + UintegerValue(6653), + MakeUintegerAccessor(&OFSwitch13Controller::m_port), + MakeUintegerChecker()); return tid; } @@ -83,7 +82,7 @@ OFSwitch13Controller::DpctlExecute(uint64_t dpId, const std::string textCmd) if (!swtch) { // Save this command for further execution after handshake procedure. - NS_LOG_DEBUG("Schedulling command for an unregistered switch."); + NS_LOG_DEBUG("Scheduling command for an unregistered switch."); auto it = m_commandsMap.find(dpId); if (it == m_commandsMap.end()) { @@ -116,8 +115,7 @@ OFSwitch13Controller::DpctlExecute(uint64_t dpId, const std::string textCmd) } void -OFSwitch13Controller::DpctlSendAndPrint(struct vconn* vconn, - struct ofl_msg_header* msg) +OFSwitch13Controller::DpctlSendAndPrint(struct vconn* vconn, struct ofl_msg_header* msg) { NS_LOG_FUNCTION_NOARGS(); @@ -139,12 +137,10 @@ OFSwitch13Controller::StartApplication() m_serverSocket->Listen(); // Setting socket callbacks - m_serverSocket->SetAcceptCallback( - MakeCallback(&OFSwitch13Controller::SocketRequest, this), - MakeCallback(&OFSwitch13Controller::SocketAccept, this)); - m_serverSocket->SetCloseCallbacks( - MakeCallback(&OFSwitch13Controller::SocketPeerClose, this), - MakeCallback(&OFSwitch13Controller::SocketPeerError, this)); + m_serverSocket->SetAcceptCallback(MakeCallback(&OFSwitch13Controller::SocketRequest, this), + MakeCallback(&OFSwitch13Controller::SocketAccept, this)); + m_serverSocket->SetCloseCallbacks(MakeCallback(&OFSwitch13Controller::SocketPeerClose, this), + MakeCallback(&OFSwitch13Controller::SocketPeerError, this)); } void @@ -204,8 +200,8 @@ OFSwitch13Controller::SendToSwitch(Ptr swtch, NS_LOG_FUNCTION(this << swtch); char* msgStr = ofl_msg_to_string(msg, nullptr); - NS_LOG_DEBUG("TX to switch " << swtch->GetIpv4() << " [dp " - << swtch->GetDpId() << "]: " << msgStr); + NS_LOG_DEBUG("TX to switch " << swtch->GetIpv4() << " [dp " << swtch->GetDpId() + << "]: " << msgStr); free(msgStr); // Set the transaction ID only for unknown values @@ -219,8 +215,7 @@ OFSwitch13Controller::SendToSwitch(Ptr swtch, } void -OFSwitch13Controller::SendEchoRequest(Ptr swtch, - size_t payloadSize) +OFSwitch13Controller::SendEchoRequest(Ptr swtch, size_t payloadSize) { NS_LOG_FUNCTION(this << swtch); @@ -306,14 +301,13 @@ OFSwitch13Controller::HandleEchoReply(struct ofl_msg_echo* msg, auto it = m_echoMap.find(xid); if (it == m_echoMap.end()) { - NS_LOG_WARN("Echo response for unknonw echo request."); + NS_LOG_WARN("Echo response for unknown echo request."); } else { it->second.m_waiting = false; it->second.m_recv = Simulator::Now(); - NS_LOG_INFO("Echo reply from " << it->second.m_swtch->GetIpv4() - << " with RTT " + NS_LOG_INFO("Echo reply from " << it->second.m_swtch->GetIpv4() << " with RTT " << it->second.GetRtt().As(Time::MS)); m_echoMap.erase(it); } @@ -332,7 +326,7 @@ OFSwitch13Controller::HandleBarrierReply(struct ofl_msg_header* msg, auto it = m_barrierMap.find(xid); if (it == m_barrierMap.end()) { - NS_LOG_WARN("Barrier response for unknonw barrier request."); + NS_LOG_WARN("Barrier response for unknown barrier request."); } else { @@ -475,10 +469,9 @@ OFSwitch13Controller::HandleAsyncReply(struct ofl_msg_async_config* msg, } ofl_err -OFSwitch13Controller::HandleMultipartReply( - struct ofl_msg_multipart_reply_header* msg, - Ptr swtch, - uint32_t xid) +OFSwitch13Controller::HandleMultipartReply(struct ofl_msg_multipart_reply_header* msg, + Ptr swtch, + uint32_t xid) { NS_LOG_FUNCTION(this << swtch << xid); @@ -498,10 +491,9 @@ OFSwitch13Controller::HandleRoleReply(struct ofl_msg_role_request* msg, } ofl_err -OFSwitch13Controller::HandleQueueGetConfigReply( - struct ofl_msg_queue_get_config_reply* msg, - Ptr swtch, - uint32_t xid) +OFSwitch13Controller::HandleQueueGetConfigReply(struct ofl_msg_queue_get_config_reply* msg, + Ptr swtch, + uint32_t xid) { NS_LOG_FUNCTION(this << swtch << xid); @@ -541,14 +533,10 @@ OFSwitch13Controller::HandleSwitchMsg(struct ofl_msg_header* msg, return HandleError((struct ofl_msg_error*)msg, swtch, xid); case OFPT_FEATURES_REPLY: - return HandleFeaturesReply((struct ofl_msg_features_reply*)msg, - swtch, - xid); + return HandleFeaturesReply((struct ofl_msg_features_reply*)msg, swtch, xid); case OFPT_GET_CONFIG_REPLY: - return HandleGetConfigReply((struct ofl_msg_get_config_reply*)msg, - swtch, - xid); + return HandleGetConfigReply((struct ofl_msg_get_config_reply*)msg, swtch, xid); case OFPT_FLOW_REMOVED: return HandleFlowRemoved((struct ofl_msg_flow_removed*)msg, swtch, xid); @@ -560,18 +548,13 @@ OFSwitch13Controller::HandleSwitchMsg(struct ofl_msg_header* msg, return HandleAsyncReply((struct ofl_msg_async_config*)msg, swtch, xid); case OFPT_MULTIPART_REPLY: - return HandleMultipartReply((struct ofl_msg_multipart_reply_header*)msg, - swtch, - xid); + return HandleMultipartReply((struct ofl_msg_multipart_reply_header*)msg, swtch, xid); case OFPT_ROLE_REPLY: return HandleRoleReply((struct ofl_msg_role_request*)msg, swtch, xid); case OFPT_QUEUE_GET_CONFIG_REPLY: - return HandleQueueGetConfigReply( - (struct ofl_msg_queue_get_config_reply*)msg, - swtch, - xid); + return HandleQueueGetConfigReply((struct ofl_msg_queue_get_config_reply*)msg, swtch, xid); case OFPT_EXPERIMENTER: default: @@ -590,18 +573,15 @@ OFSwitch13Controller::ReceiveFromSwitch(Ptr packet, Address from) // Get the openflow buffer, unpack the message and send to message handler struct ofpbuf* buffer = BufferFromPacket(packet, packet->GetSize()); - error = ofl_msg_unpack((uint8_t*)buffer->data, - buffer->size, - &msg, - &xid, - nullptr); + error = ofl_msg_unpack((uint8_t*)buffer->data, buffer->size, &msg, &xid, nullptr); if (!error) { Ptr swtch = GetRemoteSwitch(from); char* msgStr = ofl_msg_to_string(msg, nullptr); - NS_LOG_DEBUG("RX from switch " << swtch->GetIpv4() << " [dp " - << swtch->GetDpId() << "]: " << msgStr); + Ipv4Address swIpv4 = swtch->GetIpv4(); + uint64_t swDpId = swtch->GetDpId(); + NS_LOG_DEBUG("RX from switch " << swIpv4 << " [dp " << swDpId << "]: " << msgStr); free(msgStr); error = HandleSwitchMsg(msg, swtch, xid); diff --git a/model/ofswitch13-controller.h b/model/ofswitch13-controller.h index 179e473..81eb7c3 100644 --- a/model/ofswitch13-controller.h +++ b/model/ofswitch13-controller.h @@ -34,12 +34,12 @@ namespace ns3 /** * \ingroup ofswitch13 * OpenFlow 1.3 controller base class that can handle a collection of OpenFlow - * switches and provides the basic functionalities for controller - * implementation. For constructing OpenFlow configuration messages and sending - * them to the switches, this class uses the DpctlCommand function, which - * relies on command-line syntax from the dpctl utility. For OpenFlow messages - * coming from the switches, this class provides a collection of internal - * handlers to deal with the different types of messages. + * switches and provides the basic functionality for controller implementation. + * For constructing OpenFlow configuration messages and sending them to the + * switches, this class uses the DpctlCommand function, which relies on + * command-line syntax from the dpctl utility. For OpenFlow messages coming from + * the switches, this class provides a collection of internal handlers to deal + * with the different types of messages. */ class OFSwitch13Controller : public Application { @@ -80,11 +80,10 @@ class OFSwitch13Controller : public Application Address m_address; //!< Switch connection address. Ptr m_ctrlApp; //!< Controller application. uint64_t m_dpId; //!< OpenFlow datapath ID. - enum ofp_controller_role m_role; //!< Controller role over switch. + enum ofp_controller_role m_role; //!< Controller role over switch. /** - * Switch features informed to the controller during handshake - * procedure. + * Switch features informed to controller during handshake procedure. */ //\{ uint32_t m_nBuffers; //!< Max packets buffered at once. @@ -184,16 +183,15 @@ class OFSwitch13Controller : public Application int DpctlExecute(uint64_t dpId, const std::string textCmd); /** - * Overriding BOFUSS dpctl_send_and_print and - * dpctl_transact_and_print weak functions from utilities/dpctl.c. Send a - * message from controller to switch. + * Overriding BOFUSS dpctl_send_and_print() and dpctl_transact_and_print() + * weak functions from utilities/dpctl.c. Send a message from controller to + * switch. * \param vconn The RemoteSwitch pointer, sent from controller to - * dpctl_exec_ns3_command function and get back here to proper identify the - * controller object. + * dpctl_exec_ns3_command() function and get back here to proper identify + * the controller object. * \param msg The OFLib message to send. */ - static void DpctlSendAndPrint(struct vconn* vconn, - struct ofl_msg_header* msg); + static void DpctlSendAndPrint(struct vconn* vconn, struct ofl_msg_header* msg); protected: // inherited from Application @@ -206,10 +204,11 @@ class OFSwitch13Controller : public Application uint32_t GetNextXid(); /** - * Function invoked after a successfully handshake procedure between - * this controller and a remote switch. Derived classes can override this + * Function invoked after a successfully handshake procedure between this + * controller and a remote switch. Derived classes can override this * function to implement any relevant logic, as sending initial - * configuration messages to the switch. \param swtch The remote switch. + * configuration messages to the switch. + * \param swtch The remote switch. */ virtual void HandshakeSuccessful(Ptr swtch); @@ -227,23 +226,22 @@ class OFSwitch13Controller : public Application * \param xid The transaction id to use. * \return 0 if everything's ok, otherwise an error number. */ - int SendToSwitch(Ptr swtch, - struct ofl_msg_header* msg, - uint32_t xid = 0); + int SendToSwitch(Ptr swtch, struct ofl_msg_header* msg, uint32_t xid = 0); /** - * Send an echo request message to switch, and wait for a non-blocking - * reply. \param swtch The remote switch to receive the message. \param - * payloadSize The ammount of dummy bytes in echo message. + * Send an echo request message to switch and wait for a non-blocking reply. + * \param swtch The remote switch to receive the message. + * \param payloadSize The amount of dummy bytes in echo message. */ void SendEchoRequest(Ptr swtch, size_t payloadSize = 0); /** - * Send a barrier request message to switch, and wait for a non-blocking + * Send a barrier request message to switch and wait for a non-blocking * reply. Note that current OpenFlow device implementation is * single-threaded and messages are processed in the same order that are * received from the controller, so a barrier request will simply be replied - * by the switch. \param swtch The remote switch to receive the message. + * by the switch. + * \param swtch The remote switch to receive the message. */ void SendBarrierRequest(Ptr swtch); @@ -256,7 +254,7 @@ class OFSwitch13Controller : public Application * just free the received message and returns 0. Derived controllers can * override them as they wish to implement the desired control logic. * - * Note that for HandleMultipartReply there are several types of multipart + * Note that for HandleMultipartReply() there are several types of multipart * messages. Derived controllers can filter by the type they wish. * * \attention Handlers \em MUST free received msg when everything is ok. @@ -266,6 +264,7 @@ class OFSwitch13Controller : public Application * \return 0 if everything's ok, otherwise an error number. */ //\{ + // clang-format off ofl_err HandleEchoRequest(struct ofl_msg_echo* msg, Ptr swtch, uint32_t xid); @@ -310,33 +309,30 @@ class OFSwitch13Controller : public Application Ptr swtch, uint32_t xid); - virtual ofl_err HandleMultipartReply( - struct ofl_msg_multipart_reply_header* msg, - Ptr swtch, - uint32_t xid); + virtual ofl_err HandleMultipartReply(struct ofl_msg_multipart_reply_header* msg, + Ptr swtch, + uint32_t xid); virtual ofl_err HandleRoleReply(struct ofl_msg_role_request* msg, Ptr swtch, uint32_t xid); - virtual ofl_err HandleQueueGetConfigReply( - struct ofl_msg_queue_get_config_reply* msg, - Ptr swtch, - uint32_t xid); + virtual ofl_err HandleQueueGetConfigReply(struct ofl_msg_queue_get_config_reply* msg, + Ptr swtch, + uint32_t xid); + // clang-format on //\} private: /** - * Called when an OpenFlow message is received from a switch. - * Dispatches control messages to appropriate handler functions. + * Called when an OpenFlow message is received from a switch. Dispatch + * control messages to appropriate handler functions. * \param msg The OFLib message received. * \param swtch The remote switch the message was received from. * \param xid The transaction id. * \return 0 if everything's ok, otherwise an error number. */ - ofl_err HandleSwitchMsg(struct ofl_msg_header* msg, - Ptr swtch, - uint32_t xid); + ofl_err HandleSwitchMsg(struct ofl_msg_header* msg, Ptr swtch, uint32_t xid); /** * Receive an OpenFlow packet from switch. diff --git a/model/ofswitch13-device.cc b/model/ofswitch13-device.cc index 0394d13..fcd5c41 100644 --- a/model/ofswitch13-device.cc +++ b/model/ofswitch13-device.cc @@ -24,10 +24,10 @@ #include #undef NS_LOG_APPEND_CONTEXT -#define NS_LOG_APPEND_CONTEXT \ - if (m_dpId) \ - { \ - std::clog << "[dp " << m_dpId << "] "; \ +#define NS_LOG_APPEND_CONTEXT \ + if (m_dpId) \ + { \ + std::clog << "[dp " << m_dpId << "] "; \ } namespace ns3 @@ -74,139 +74,117 @@ OFSwitch13Device::GetTypeId() .SetParent() .SetGroupName("OFSwitch13") .AddConstructor() - .AddAttribute( - "CpuCapacity", - "CPU processing capacity (in terms of throughput).", - DataRateValue(DataRate("100Gb/s")), - MakeDataRateAccessor(&OFSwitch13Device::m_cpuCapacity), - MakeDataRateChecker()) + .AddAttribute("CpuCapacity", + "CPU processing capacity (in terms of throughput).", + DataRateValue(DataRate("100Gb/s")), + MakeDataRateAccessor(&OFSwitch13Device::m_cpuCapacity), + MakeDataRateChecker()) .AddAttribute("DatapathId", "The unique identification of this OpenFlow switch.", TypeId::ATTR_GET, UintegerValue(0), MakeUintegerAccessor(&OFSwitch13Device::m_dpId), MakeUintegerChecker()) - .AddAttribute( - "FlowTableSize", - "The maximum number of entries allowed on each flow table.", - UintegerValue(FLOW_TABLE_MAX_ENTRIES), - MakeUintegerAccessor(&OFSwitch13Device::SetDftFlowTableSize, - &OFSwitch13Device::GetDftFlowTableSize), - MakeUintegerChecker(0, FLOW_TABLE_MAX_ENTRIES)) - .AddAttribute( - "GroupTableSize", - "The maximum number of entries allowed on group table.", - UintegerValue(GROUP_TABLE_MAX_ENTRIES), - MakeUintegerAccessor(&OFSwitch13Device::SetGroupTableSize, - &OFSwitch13Device::GetGroupTableSize), - MakeUintegerChecker(0, GROUP_TABLE_MAX_ENTRIES)) - .AddAttribute( - "MeterTableSize", - "The maximum number of entries allowed on meter table.", - UintegerValue(METER_TABLE_MAX_ENTRIES), - MakeUintegerAccessor(&OFSwitch13Device::SetMeterTableSize, - &OFSwitch13Device::GetMeterTableSize), - MakeUintegerChecker(0, METER_TABLE_MAX_ENTRIES)) - .AddAttribute( - "PipelineTables", - "The number of pipeline flow tables.", - TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, - UintegerValue(64), - MakeUintegerAccessor(&OFSwitch13Device::m_numPipeTabs), - MakeUintegerChecker(1, (OFPTT_MAX + 1))) + .AddAttribute("FlowTableSize", + "The maximum number of entries allowed on each flow table.", + UintegerValue(FLOW_TABLE_MAX_ENTRIES), + MakeUintegerAccessor(&OFSwitch13Device::SetDftFlowTableSize, + &OFSwitch13Device::GetDftFlowTableSize), + MakeUintegerChecker(0, FLOW_TABLE_MAX_ENTRIES)) + .AddAttribute("GroupTableSize", + "The maximum number of entries allowed on group table.", + UintegerValue(GROUP_TABLE_MAX_ENTRIES), + MakeUintegerAccessor(&OFSwitch13Device::SetGroupTableSize, + &OFSwitch13Device::GetGroupTableSize), + MakeUintegerChecker(0, GROUP_TABLE_MAX_ENTRIES)) + .AddAttribute("MeterTableSize", + "The maximum number of entries allowed on meter table.", + UintegerValue(METER_TABLE_MAX_ENTRIES), + MakeUintegerAccessor(&OFSwitch13Device::SetMeterTableSize, + &OFSwitch13Device::GetMeterTableSize), + MakeUintegerChecker(0, METER_TABLE_MAX_ENTRIES)) + .AddAttribute("PipelineTables", + "The number of pipeline flow tables.", + TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, + UintegerValue(64), + MakeUintegerAccessor(&OFSwitch13Device::m_numPipeTabs), + MakeUintegerChecker(1, (OFPTT_MAX + 1))) .AddAttribute("PortList", "The list of ports associated to this switch.", ObjectVectorValue(), MakeObjectVectorAccessor(&OFSwitch13Device::m_ports), MakeObjectVectorChecker()) - .AddAttribute( - "TcamDelay", - "Average time to perform a TCAM operation in pipeline.", - TimeValue(MicroSeconds(20)), - MakeTimeAccessor(&OFSwitch13Device::m_tcamDelay), - MakeTimeChecker(Time(0))) - .AddAttribute( - "TimeoutInterval", - "The interval between timeout operations on datapath.", - TimeValue(MilliSeconds(100)), - MakeTimeAccessor(&OFSwitch13Device::m_timeout), - MakeTimeChecker(MilliSeconds(1), MilliSeconds(1000))) - - .AddTraceSource( - "BufferExpire", - "Trace source indicating an expired packet in buffer.", - MakeTraceSourceAccessor(&OFSwitch13Device::m_bufferExpireTrace), - "ns3::Packet::TracedCallback") - .AddTraceSource( - "BufferRetrieve", - "Trace source indicating a packet retrieved from buffer.", - MakeTraceSourceAccessor( - &OFSwitch13Device::m_bufferRetrieveTrace), - "ns3::Packet::TracedCallback") - .AddTraceSource( - "BufferSave", - "Trace source indicating a packet saved into buffer.", - MakeTraceSourceAccessor(&OFSwitch13Device::m_bufferSaveTrace), - "ns3::Packet::TracedCallback") - .AddTraceSource( - "MeterDrop", - "Trace source indicating a packet dropped by meter band.", - MakeTraceSourceAccessor(&OFSwitch13Device::m_meterDropTrace), - "ns3::OFSwitch13Device::MeterDropTracedCallback") - .AddTraceSource( - "OverloadDrop", - "Trace source indicating a packet dropped by CPU " - "overloaded processing capacity.", - MakeTraceSourceAccessor(&OFSwitch13Device::m_loadDropTrace), - "ns3::Packet::TracedCallback") - .AddTraceSource( - "TableDrop", - "Trace source indicating an unmatched packet dropped by " - "a flow table without a table-miss entry.", - MakeTraceSourceAccessor(&OFSwitch13Device::m_tableDropTrace), - "ns3::OFSwitch13Device::TableDropTracedCallback") - .AddTraceSource( - "PipelinePacket", - "Trace source indicating a packet sent to pipeline.", - MakeTraceSourceAccessor(&OFSwitch13Device::m_pipePacketTrace), - "ns3::Packet::TracedCallback") - .AddTraceSource( - "DatapathTimeout", - "Trace source indicating a datapath timeout operation.", - MakeTraceSourceAccessor( - &OFSwitch13Device::m_datapathTimeoutTrace), - "ns3::OFSwitch13Device::DeviceTracedCallback") - - .AddTraceSource( - "CpuLoad", - "Traced value indicating the avg CPU processing load" - " (periodically updated on datapath timeout operation).", - MakeTraceSourceAccessor(&OFSwitch13Device::m_cpuLoad), - "ns3::TracedValueCallback::DataRate") - .AddTraceSource( - "GroupEntries", - "Traced value indicating the number of group entries" - " (periodically updated on datapath timeout operation).", - MakeTraceSourceAccessor(&OFSwitch13Device::m_groupEntries), - "ns3::TracedValueCallback::Uint32") - .AddTraceSource( - "MeterEntries", - "Traced value indicating the number of meter entries" - " (periodically updated on datapath timeout operation).", - MakeTraceSourceAccessor(&OFSwitch13Device::m_meterEntries), - "ns3::TracedValueCallback::Uint32") - .AddTraceSource( - "PipelineDelay", - "Traced value indicating the avg pipeline lookup delay" - " (periodically updated on datapath timeout operation).", - MakeTraceSourceAccessor(&OFSwitch13Device::m_pipeDelay), - "ns3::TracedValueCallback::Time") - .AddTraceSource( - "SumFlowEntries", - "Traced value indicating the total number of flow entries" - " (periodically updated on datapath timeout operation).", - MakeTraceSourceAccessor(&OFSwitch13Device::m_sumFlowEntries), - "ns3::TracedValueCallback::Uint32"); + .AddAttribute("TcamDelay", + "Average time to perform a TCAM operation in pipeline.", + TimeValue(MicroSeconds(20)), + MakeTimeAccessor(&OFSwitch13Device::m_tcamDelay), + MakeTimeChecker(Time(0))) + .AddAttribute("TimeoutInterval", + "The interval between timeout operations on datapath.", + TimeValue(MilliSeconds(100)), + MakeTimeAccessor(&OFSwitch13Device::m_timeout), + MakeTimeChecker(MilliSeconds(1), MilliSeconds(1000))) + + .AddTraceSource("BufferExpire", + "Trace source indicating an expired packet in buffer.", + MakeTraceSourceAccessor(&OFSwitch13Device::m_bufferExpireTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource("BufferRetrieve", + "Trace source indicating a packet retrieved from buffer.", + MakeTraceSourceAccessor(&OFSwitch13Device::m_bufferRetrieveTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource("BufferSave", + "Trace source indicating a packet saved into buffer.", + MakeTraceSourceAccessor(&OFSwitch13Device::m_bufferSaveTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource("MeterDrop", + "Trace source indicating a packet dropped by meter band.", + MakeTraceSourceAccessor(&OFSwitch13Device::m_meterDropTrace), + "ns3::OFSwitch13Device::MeterDropTracedCallback") + .AddTraceSource("OverloadDrop", + "Trace source indicating a packet dropped by CPU " + "overloaded processing capacity.", + MakeTraceSourceAccessor(&OFSwitch13Device::m_loadDropTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource("TableDrop", + "Trace source indicating an unmatched packet dropped by " + "a flow table without a table-miss entry.", + MakeTraceSourceAccessor(&OFSwitch13Device::m_tableDropTrace), + "ns3::OFSwitch13Device::TableDropTracedCallback") + .AddTraceSource("PipelinePacket", + "Trace source indicating a packet sent to pipeline.", + MakeTraceSourceAccessor(&OFSwitch13Device::m_pipePacketTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource("DatapathTimeout", + "Trace source indicating a datapath timeout operation.", + MakeTraceSourceAccessor(&OFSwitch13Device::m_datapathTimeoutTrace), + "ns3::OFSwitch13Device::DeviceTracedCallback") + + .AddTraceSource("CpuLoad", + "Traced value indicating the avg CPU processing load" + " (periodically updated on datapath timeout operation).", + MakeTraceSourceAccessor(&OFSwitch13Device::m_cpuLoad), + "ns3::TracedValueCallback::DataRate") + .AddTraceSource("GroupEntries", + "Traced value indicating the number of group entries" + " (periodically updated on datapath timeout operation).", + MakeTraceSourceAccessor(&OFSwitch13Device::m_groupEntries), + "ns3::TracedValueCallback::Uint32") + .AddTraceSource("MeterEntries", + "Traced value indicating the number of meter entries" + " (periodically updated on datapath timeout operation).", + MakeTraceSourceAccessor(&OFSwitch13Device::m_meterEntries), + "ns3::TracedValueCallback::Uint32") + .AddTraceSource("PipelineDelay", + "Traced value indicating the avg pipeline lookup delay" + " (periodically updated on datapath timeout operation).", + MakeTraceSourceAccessor(&OFSwitch13Device::m_pipeDelay), + "ns3::TracedValueCallback::Time") + .AddTraceSource("SumFlowEntries", + "Traced value indicating the total number of flow entries" + " (periodically updated on datapath timeout operation).", + MakeTraceSourceAccessor(&OFSwitch13Device::m_sumFlowEntries), + "ns3::TracedValueCallback::Uint32"); return tid; } @@ -271,8 +249,7 @@ OFSwitch13Device::GetBufferUsage() const { return 0.0; } - return static_cast(GetBufferEntries()) / - static_cast(GetBufferSize()); + return static_cast(GetBufferEntries()) / static_cast(GetBufferSize()); } DataRate @@ -357,8 +334,7 @@ OFSwitch13Device::GetGroupTableUsage() const { return 0.0; } - return static_cast(GetGroupTableEntries()) / - static_cast(GetGroupTableSize()); + return static_cast(GetGroupTableEntries()) / static_cast(GetGroupTableSize()); } uint32_t @@ -381,8 +357,7 @@ OFSwitch13Device::GetMeterTableUsage() const { return 0.0; } - return static_cast(GetMeterTableEntries()) / - static_cast(GetMeterTableSize()); + return static_cast(GetMeterTableEntries()) / static_cast(GetMeterTableSize()); } uint32_t @@ -432,17 +407,14 @@ OFSwitch13Device::AddSwitchPort(Ptr portDevice) NS_LOG_FUNCTION(this << portDevice); NS_LOG_INFO("Adding port addr " << portDevice->GetAddress()); - NS_ABORT_MSG_IF(GetNSwitchPorts() >= DP_MAX_PORTS, - "No more ports allowed."); + NS_ABORT_MSG_IF(GetNSwitchPorts() >= DP_MAX_PORTS, "No more ports allowed."); // Create the OpenFlow port for this device. - Ptr ofPort; - ofPort = CreateObject(m_datapath, portDevice, this); + Ptr ofPort = CreateObject(m_datapath, portDevice, this); // Save port in port list (assert port no and vector index). m_ports.emplace_back(ofPort); - NS_ASSERT((m_ports.size() == ofPort->GetPortNo()) && - (m_ports.size() == m_datapath->ports_num)); + NS_ASSERT((m_ports.size() == ofPort->GetPortNo()) && (m_ports.size() == m_datapath->ports_num)); return ofPort; } @@ -458,9 +430,7 @@ OFSwitch13Device::GetSwitchPort(uint32_t no) const } void -OFSwitch13Device::ReceiveFromSwitchPort(Ptr packet, - uint32_t portNo, - uint64_t tunnelId) +OFSwitch13Device::ReceiveFromSwitchPort(Ptr packet, uint32_t portNo, uint64_t tunnelId) { NS_LOG_FUNCTION(this << packet << portNo << tunnelId); @@ -495,8 +465,7 @@ OFSwitch13Device::StartControllerConnection(Address ctrlAddr) NS_ASSERT(!ctrlAddr.IsInvalid()); NS_ASSERT_MSG(InetSocketAddress::IsMatchingType(ctrlAddr), "Invalid address type (only IPv4 supported by now)."); - NS_ASSERT_MSG(!GetRemoteController(ctrlAddr), - "Controller address already in use."); + NS_ASSERT_MSG(!GetRemoteController(ctrlAddr), "Controller address already in use."); // Start a TCP connection to this target controller. int error = 0; @@ -518,9 +487,8 @@ OFSwitch13Device::StartControllerConnection(Address ctrlAddr) return; } - ctrlSocket->SetConnectCallback( - MakeCallback(&OFSwitch13Device::SocketCtrlSucceeded, this), - MakeCallback(&OFSwitch13Device::SocketCtrlFailed, this)); + ctrlSocket->SetConnectCallback(MakeCallback(&OFSwitch13Device::SocketCtrlSucceeded, this), + MakeCallback(&OFSwitch13Device::SocketCtrlFailed, this)); // Create a RemoteController object for this controller and save it. Ptr remoteCtrl = Create(); @@ -537,15 +505,11 @@ OFSwitch13Device::SendPacketToController(struct pipeline* pl, uint8_t reason) { Ptr dev = OFSwitch13Device::GetDevice(pl->dp->id); - dev->SendPacketInMessage(pkt, - tableId, - reason, - dev->m_datapath->config.miss_send_len); + dev->SendPacketInMessage(pkt, tableId, reason, dev->m_datapath->config.miss_send_len); } int -OFSwitch13Device::SendOpenflowBufferToRemote(struct ofpbuf* buffer, - struct remote* remote) +OFSwitch13Device::SendOpenflowBufferToRemote(struct ofpbuf* buffer, struct remote* remote) { Ptr dev = OFSwitch13Device::GetDevice(remote->dp->id); Ptr packet = PacketFromBuffer(buffer); @@ -584,8 +548,7 @@ OFSwitch13Device::DpActionsOutputPort(struct packet* pkt, case (OFPP_CONTROLLER): { dev->SendPacketInMessage(pkt, pkt->table_id, - pkt->handle_std->table_miss ? OFPR_NO_MATCH - : OFPR_ACTION, + pkt->handle_std->table_miss ? OFPR_NO_MATCH : OFPR_ACTION, maxLength, cookie); break; @@ -623,16 +586,14 @@ OFSwitch13Device::MeterCreatedCallback(struct meter_entry* entry) } void -OFSwitch13Device::MeterDropCallback(struct packet* pkt, - struct meter_entry* entry) +OFSwitch13Device::MeterDropCallback(struct packet* pkt, struct meter_entry* entry) { Ptr dev = OFSwitch13Device::GetDevice(pkt->dp->id); dev->NotifyPacketDroppedByMeter(pkt, entry); } void -OFSwitch13Device::TableDropCallback(struct packet* pkt, - struct flow_table* table) +OFSwitch13Device::TableDropCallback(struct packet* pkt, struct flow_table* table) { Ptr dev = OFSwitch13Device::GetDevice(pkt->dp->id); dev->NotifyPacketDroppedByTable(pkt, table); @@ -653,7 +614,7 @@ OFSwitch13Device::PacketDestroyCallback(struct packet* pkt) } void -OFSwitch13Device::BufferSaveCallback(struct packet* pkt, time_t timeout) +OFSwitch13Device::BufferSaveCallback(struct packet* pkt, uint64_t timeout) { Ptr dev = OFSwitch13Device::GetDevice(pkt->dp->id); dev->BufferPacketSave(pkt->ns3_uid, timeout); @@ -722,7 +683,7 @@ OFSwitch13Device::NotifyConstructionCompleted() // Create the datapath. m_datapath = DatapathNew(); - // Set the attribute values again so it can now update the dapatah structs. + // Set the attribute values again so it can now update the datapath structs. SetDftFlowTableSize(GetDftFlowTableSize()); SetGroupTableSize(GetGroupTableSize()); SetMeterTableSize(GetMeterTableSize()); @@ -779,8 +740,7 @@ OFSwitch13Device::DatapathNew() dp->max_queues = PORT_MAX_QUEUES; dp->exp = nullptr; - dp->config.flags = - OFPC_FRAG_NORMAL; // IP fragments with no special handling + dp->config.flags = OFPC_FRAG_NORMAL; // IP fragments with no special handling dp->config.miss_send_len = OFP_DEFAULT_MISS_SEND_LEN; // 128 bytes // BOFUSS callbacks @@ -801,8 +761,7 @@ OFSwitch13Device::SetFlowTableSize(uint8_t tableId, uint32_t value) NS_LOG_FUNCTION(this << tableId << value); NS_ASSERT_MSG(m_datapath, "No datapath defined yet."); - NS_ABORT_MSG_IF(GetFlowTableEntries(tableId) > value, - "Can't reduce table size to this value."); + NS_ABORT_MSG_IF(GetFlowTableEntries(tableId) > value, "Can't reduce table size to this value."); m_datapath->pipeline->tables[tableId]->features->max_entries = value; } @@ -829,8 +788,7 @@ OFSwitch13Device::SetGroupTableSize(uint32_t value) m_groupTabSize = value; if (m_datapath) { - NS_ABORT_MSG_IF(GetGroupTableEntries() > value, - "Can't reduce table size to this value."); + NS_ABORT_MSG_IF(GetGroupTableEntries() > value, "Can't reduce table size to this value."); for (size_t i = 0; i < 4; i++) { m_datapath->groups->features->max_groups[i] = value; @@ -846,8 +804,7 @@ OFSwitch13Device::SetMeterTableSize(uint32_t value) m_meterTabSize = value; if (m_datapath) { - NS_ABORT_MSG_IF(GetMeterTableEntries() > value, - "Can't reduce table size to this value."); + NS_ABORT_MSG_IF(GetMeterTableEntries() > value, "Can't reduce table size to this value."); m_datapath->meters->features->max_meter = value; } } @@ -872,11 +829,9 @@ OFSwitch13Device::DatapathTimeout(struct datapath* dp) // The pipeline delay is estimated as k * log (n), where 'k' is the // m_tcamDelay set to the time for a single TCAM operation, and 'n' is the // current number of entries on all flow tables. - m_pipeDelay = - m_sumFlowEntries < 2U - ? m_tcamDelay - : m_tcamDelay * - (int64_t)ceil(log2(static_cast(m_sumFlowEntries))); + m_pipeDelay = m_sumFlowEntries < 2U + ? m_tcamDelay + : m_tcamDelay * (int64_t)ceil(log2(static_cast(m_sumFlowEntries))); // The CPU load is estimated based on the CPU consumed tokens since last // timeout operation. @@ -885,18 +840,15 @@ OFSwitch13Device::DatapathTimeout(struct datapath* dp) // Refill the pipeline bucket with tokens based on elapsed time // (bucket capacity is set to the number of tokens for an entire second). - Time elapTime = Simulator::Now() - m_lastTimeout; - uint64_t addTokens = m_cpuCapacity.GetBitRate() * elapTime.GetSeconds(); + Time elapsedTime = Simulator::Now() - m_lastTimeout; + uint64_t addTokens = m_cpuCapacity.GetBitRate() * elapsedTime.GetSeconds(); uint64_t maxTokens = m_cpuCapacity.GetBitRate(); m_cpuTokens = std::min(m_cpuTokens + addTokens, maxTokens); dp->last_timeout = time_now(); m_lastTimeout = Simulator::Now(); m_datapathTimeoutTrace(this); - Simulator::Schedule(m_timeout, - &OFSwitch13Device::DatapathTimeout, - this, - m_datapath); + Simulator::Schedule(m_timeout, &OFSwitch13Device::DatapathTimeout, this, m_datapath); } int @@ -938,9 +890,7 @@ OFSwitch13Device::SendPacketInMessage(struct packet* pkt, } bool -OFSwitch13Device::SendToSwitchPort(struct packet* pkt, - uint32_t portNo, - uint32_t queueNo) +OFSwitch13Device::SendToSwitchPort(struct packet* pkt, uint32_t portNo, uint32_t queueNo) { NS_LOG_FUNCTION(this << pkt->ns3_uid << portNo); @@ -992,9 +942,7 @@ OFSwitch13Device::SendToSwitchPort(struct packet* pkt, } void -OFSwitch13Device::SendToPipeline(Ptr packet, - uint32_t portNo, - uint64_t tunnelId) +OFSwitch13Device::SendToPipeline(Ptr packet, uint32_t portNo, uint64_t tunnelId) { NS_LOG_FUNCTION(this << packet << portNo << tunnelId); @@ -1005,8 +953,7 @@ OFSwitch13Device::SendToPipeline(Ptr packet, uint32_t headRoom = 128 + 2; uint32_t bodyRoom = packet->GetSize() + VLAN_ETH_HEADER_LEN; struct ofpbuf* buffer = BufferFromPacket(packet, bodyRoom, headRoom); - struct packet* pkt = - packet_create(m_datapath, portNo, buffer, tunnelId, false); + struct packet* pkt = packet_create(m_datapath, portNo, buffer, tunnelId, false); // Save the ns-3 packet into pipeline structure. Note that we are using a // private packet uid to avoid conflicts with ns3::Packet uid. @@ -1018,8 +965,7 @@ OFSwitch13Device::SendToPipeline(Ptr packet, } int -OFSwitch13Device::SendToController(Ptr packet, - Ptr remoteCtrl) +OFSwitch13Device::SendToController(Ptr packet, Ptr remoteCtrl) { if (!remoteCtrl->m_socket) { @@ -1057,7 +1003,7 @@ OFSwitch13Device::ReceiveFromController(Ptr packet, Address from) // Check for error while unpacking the message. if (error) { - // The BOFUSS librady only unpacks messages that has the same + // The BOFUSS library only unpacks messages that has the same // OFP_VERSION that is supported by the datapath implementation. // However, when an OpenFlow connection is first established, each side // of the connection must immediately send an OFPT_HELLO message with @@ -1163,9 +1109,7 @@ OFSwitch13Device::ReplyWithErrorMessage(ofl_err error, NS_LOG_ERROR("Error processing OpenFlow message. Reply with " << msgStr); free(msgStr); - return dp_send_message(m_datapath, - (struct ofl_msg_header*)&err, - senderCtrl); + return dp_send_message(m_datapath, (struct ofl_msg_header*)&err, senderCtrl); } void @@ -1267,8 +1211,7 @@ OFSwitch13Device::NotifyPacketDestroyed(struct packet* pkt) } // If we got here, this packet must not be valid on the pipeline structure. - NS_ASSERT_MSG((m_pipePkt.IsValid() && !m_pipePkt.HasId(pkt->ns3_uid)) || - !m_pipePkt.IsValid(), + NS_ASSERT_MSG((m_pipePkt.IsValid() && !m_pipePkt.HasId(pkt->ns3_uid)) || !m_pipePkt.IsValid(), "Packet still valid in pipeline."); // This destroyed packet is probably an old packet that was previously saved @@ -1280,37 +1223,33 @@ OFSwitch13Device::NotifyPacketDestroyed(struct packet* pkt) } void -OFSwitch13Device::NotifyPacketDroppedByMeter(struct packet* pkt, - struct meter_entry* entry) +OFSwitch13Device::NotifyPacketDroppedByMeter(struct packet* pkt, struct meter_entry* entry) { NS_LOG_FUNCTION(this << pkt->ns3_uid << entry->stats->meter_id); uint32_t meterId = entry->stats->meter_id; NS_ASSERT_MSG(m_pipePkt.HasId(pkt->ns3_uid), "Invalid packet ID."); - NS_LOG_DEBUG("OpenFlow meter id " << meterId << " dropped packet " - << pkt->ns3_uid); + NS_LOG_DEBUG("OpenFlow meter id " << meterId << " dropped packet " << pkt->ns3_uid); // Fire drop trace source. m_meterDropTrace(m_pipePkt.GetPacket(), meterId); } void -OFSwitch13Device::NotifyPacketDroppedByTable(struct packet* pkt, - struct flow_table* table) +OFSwitch13Device::NotifyPacketDroppedByTable(struct packet* pkt, struct flow_table* table) { NS_LOG_FUNCTION(this << pkt->ns3_uid << table->stats->table_id); uint8_t tableId = table->stats->table_id; NS_ASSERT_MSG(m_pipePkt.HasId(pkt->ns3_uid), "Invalid packet ID."); - NS_LOG_DEBUG("OpenFlow table id " - << +tableId << " dropped unmatched packet " << pkt->ns3_uid); + NS_LOG_DEBUG("OpenFlow table id " << +tableId << " dropped unmatched packet " << pkt->ns3_uid); // Fire drop trace source. m_tableDropTrace(m_pipePkt.GetPacket(), tableId); } void -OFSwitch13Device::BufferPacketSave(uint64_t packetId, time_t timeout) +OFSwitch13Device::BufferPacketSave(uint64_t packetId, uint64_t timeout) { NS_LOG_FUNCTION(this << packetId); @@ -1331,10 +1270,8 @@ OFSwitch13Device::BufferPacketSave(uint64_t packetId, time_t timeout) m_pipePkt.DelCopy(packetId); NS_ASSERT_MSG(!m_pipePkt.IsValid(), "Packet copy still in pipeline."); - // Scheduling the buffer remove for expired packet. Since packet timeout - // resolution is expressed in seconds, let's double it to avoid rounding - // conflicts. - Simulator::Schedule(Time::FromInteger(2 * timeout, Time::S), + // Scheduling the buffer removal for expired packet. + Simulator::Schedule(Time::FromInteger(timeout, Time::MS), &OFSwitch13Device::BufferPacketDelete, this, packetId); @@ -1349,7 +1286,7 @@ OFSwitch13Device::BufferPacketRetrieve(uint64_t packetId) // Find packet in buffer. auto it = m_bufferPkts.find(packetId); - NS_ASSERT_MSG(it != m_bufferPkts.end(), "Packet not found in buffer."); + NS_ABORT_MSG_IF(it == m_bufferPkts.end(), "Packet not found in buffer."); // Save packet into pipeline structure. m_pipePkt.SetPacket(it->first, it->second); diff --git a/model/ofswitch13-device.h b/model/ofswitch13-device.h index ad7051a..0ea40d8 100644 --- a/model/ofswitch13-device.h +++ b/model/ofswitch13-device.h @@ -40,15 +40,15 @@ class OFSwitch13Port; * * An OpenFlow 1.3 device that switches multiple CSMA segments via OpenFlow * protocol. It takes a collection of ports, each one associated with a ns-3 - * underlying CsmaNetDevice. The device acts as the intermediary between the + * underlying CsmaNetDevice. The device acts as the intermediate between the * ports, receiving a packet from one port and forwarding it to another. * * The OpenFlow switch datapath implementation (flow tables, group table, and - * meter table) is provided by the BOFUSS library. For this reason, - * packets entering the switch are sent to the library for OpenFlow pipeline - * processing before being forwarded to the correct output port(s). OpenFlow - * messages received from the controller are also sent to the library for - * datapath configuration. + * meter table) is provided by the BOFUSS library. For this reason, packets + * entering the switch are sent to the library for OpenFlow pipeline processing + * before being forwarded to the correct output port(s). OpenFlow messages + * received from the controller are also sent to the library for datapath + * configuration. */ class OFSwitch13Device : public Object { @@ -80,7 +80,7 @@ class OFSwitch13Device : public Object * the ID for each packet copy (notified by the clone callback). Note that * only one packet can be in pipeline at a time, but the packet can have * multiple internal copies (each one will receive an unique packet ID), and - * can also be saved into buffer for latter usage. + * can also be saved into buffer for later usage. */ struct PipelinePacket { @@ -98,7 +98,7 @@ class OFSwitch13Device : public Object /** \return The packet pointer. */ Ptr GetPacket() const; - /** Invalidate packet metatada.*/ + /** Invalidate packet metadata. */ void Invalidate(); /** @@ -150,7 +150,7 @@ class OFSwitch13Device : public Object uint64_t GetDatapathId() const; /** - * Alias for the GetDatapathId () method. + * Alias for the GetDatapathId() method. * \return The datapath ID. */ uint64_t GetDpId() const; @@ -210,8 +210,9 @@ class OFSwitch13Device : public Object * device. The current implementation only supports CsmaNetDevice (for * physical ports) or VirtualNetDevice (for logical ports). Keep in mind * that an OpenFlow switch expects to receive packets with Ethernet header - * from port devices). \param portDevice The NetDevice port to add. \return - * The OFSwitch13Port created. + * from port devices). + * \param portDevice The NetDevice port to add. + * \return The OFSwitch13Port created. */ Ptr AddSwitchPort(Ptr portDevice); @@ -224,13 +225,12 @@ class OFSwitch13Device : public Object /** * Called when a packet is received on one of the switch's ports. This - * method will schedule the packet for OpenFlow pipeline. \param packet The - * packet. \param portNo The switch input port number. \param tunnelId The - * metadata associated with a logical port. + * method will schedule the packet for OpenFlow pipeline. + * \param packet The packet. + * \param portNo The switch input port number. + * \param tunnelId The metadata associated with a logical port. */ - void ReceiveFromSwitchPort(Ptr packet, - uint32_t portNo, - uint64_t tunnelId = 0); + void ReceiveFromSwitchPort(Ptr packet, uint32_t portNo, uint64_t tunnelId = 0); /** * Starts the TCP connection between this switch and the target controller @@ -240,8 +240,8 @@ class OFSwitch13Device : public Object void StartControllerConnection(Address ctrlAddr); /** - * Overriding BOFUSS send_packet_to_controller weak function - * from udatapath/pipeline.c. Sends the given packet to controller(s) in a + * Overriding BOFUSS send_packet_to_controller weak function from + * udatapath/pipeline.c. Sends the given packet to controller(s) in a * packet_in message. * \internal * This function relies on the global map that stores OpenFlow devices to @@ -267,14 +267,13 @@ class OFSwitch13Device : public Object * \param remote The remote controller connection information. * \return 0 if everything's ok, otherwise an error number. */ - static int SendOpenflowBufferToRemote(struct ofpbuf* buffer, - struct remote* remote); + static int SendOpenflowBufferToRemote(struct ofpbuf* buffer, struct remote* remote); /** * Overriding BOFUSS dp_actions_output_port weak function from * udatapath/dp_actions.c. Outputs a datapath packet on switch port. This - * code is nearly the same on ofsoftswitch, but it gets the openflow device - * from datapath id and uses member functions to send the packet over ns3 + * code is nearly the same on BOFUSS, but it gets the openflow device from + * datapath id and uses member functions to send the packet over ns3 * structures. * \internal * This function relies on the global map that stores OpenFlow devices to @@ -302,12 +301,12 @@ class OFSwitch13Device : public Object * \param pkt The original internal packet. * \param entry The meter entry that dropped the packet. */ - static void MeterDropCallback(struct packet* pkt, - struct meter_entry* entry); + static void MeterDropCallback(struct packet* pkt, struct meter_entry* entry); /** * Callback fired when an unmatched packet is dropped by a flow table - * without a table-miss entry. \param pkt The original internal packet. + * without a table-miss entry. + * \param pkt The original internal packet. * \param table The flow table that dropped the packet. */ static void TableDropCallback(struct packet* pkt, struct flow_table* table); @@ -330,7 +329,7 @@ class OFSwitch13Device : public Object * \param pkt The internal packet saved into buffer. * \param timeout The timeout for this packet into buffer. */ - static void BufferSaveCallback(struct packet* pkt, time_t timeout); + static void BufferSaveCallback(struct packet* pkt, uint64_t timeout); /** * Callback fired when a packet is retrieved from buffer. @@ -350,8 +349,7 @@ class OFSwitch13Device : public Object * \param packet The dropped packet. * \param meterId The meter entry ID that dropped the packet. */ - typedef void (*MeterDropTracedCallback)(Ptr packet, - uint32_t meterId); + typedef void (*MeterDropTracedCallback)(Ptr packet, uint32_t meterId); /** * TracedCallback signature for unmatched packets dropped by flow tables @@ -359,12 +357,11 @@ class OFSwitch13Device : public Object * \param packet The dropped packet. * \param tableId The flow table ID that dropped the packet. */ - typedef void (*TableDropTracedCallback)(Ptr packet, - uint8_t tableId); + typedef void (*TableDropTracedCallback)(Ptr packet, uint8_t tableId); /** * TracedCallback signature for OpenFlow switch device. - * \param deve The OpenFlow switch device pointer. + * \param dev The OpenFlow switch device pointer. */ typedef void (*DeviceTracedCallback)(Ptr dev); @@ -379,7 +376,7 @@ class OFSwitch13Device : public Object /** * Creates a new datapath. * \return The created datapath. - * \see ofsoftswitch dp_new () at udatapath/datapath.c + * \see BOFUSS dp_new() at udatapath/datapath.c */ struct datapath* DatapathNew(); @@ -397,9 +394,9 @@ class OFSwitch13Device : public Object /** * Check if any flow in any table is timed out and update port status. This - * method reschedules itself at every m_timout interval, to constantly check + * method schedules itself at every m_timout interval, to periodically check * the pipeline for timed out flow entries and update port status. - * \see BOFUSS function pipeline_timeout () at udatapath/pipeline.c + * \see BOFUSS function pipeline_timeout() at udatapath/pipeline.c * \param dp The datapath. */ void DatapathTimeout(struct datapath* dp); @@ -421,17 +418,15 @@ class OFSwitch13Device : public Object uint64_t cookie = 0); /** - * Send a message over a specific switch port. Check port configuration, - * get the ns-3 packet and send the packet over the proper OpenFlow port. - * \see DpActionsOutputPort (). + * Send a message over a specific switch port. Check port configuration, get + * the ns-3 packet and send the packet over the proper OpenFlow port. + * \see DpActionsOutputPort(). * \param pkt The internal packet to send. * \param portNo The port number. * \param queueNo The queue number. * \return True if success, false otherwise. */ - bool SendToSwitchPort(struct packet* pkt, - uint32_t portNo, - uint32_t queueNo = 0); + bool SendToSwitchPort(struct packet* pkt, uint32_t portNo, uint32_t queueNo = 0); /** * Send the packet to the OpenFlow BOFUSS pipeline. @@ -439,26 +434,23 @@ class OFSwitch13Device : public Object * \param portNo The switch input port number. * \param tunnelId The metadata associated with a logical port. */ - void SendToPipeline(Ptr packet, - uint32_t portNo, - uint64_t tunnelId = 0); + void SendToPipeline(Ptr packet, uint32_t portNo, uint64_t tunnelId = 0); /** * Send a packet to the controller node. - * \see SendOpenflowBufferToRemote (). + * \see SendOpenflowBufferToRemote(). * \attention Don't use this method to directly send messages to controller. - * Use dp_send_message () instead, as it deals with multiple connections and + * Use dp_send_message() instead, as it deals with multiple connections and * check async config. * \param packet The ns-3 packet to send. * \param remoteCtrl The remote controller object to send the packet. * \return 0 if everything's ok, otherwise an error number. */ - int SendToController(Ptr packet, - Ptr remoteCtrl); + int SendToController(Ptr packet, Ptr remoteCtrl); /** * Receive an OpenFlow packet from controller. - * \see remote_rconn_run () at udatapath/datapath.c. + * \see remote_rconn_run() at udatapath/datapath.c. * \param packet The packet with the OpenFlow message. * \param from The packet sender address. */ @@ -473,9 +465,7 @@ class OFSwitch13Device : public Object * \param senderCtrl The origin of a received OpenFlow message. * \return 0 if everything's ok, otherwise an error number. */ - int ReplyWithErrorMessage(ofl_err error, - struct ofpbuf* buffer, - struct sender* senderCtrl); + int ReplyWithErrorMessage(ofl_err error, struct ofpbuf* buffer, struct sender* senderCtrl); /** * Socket callback fired when a TCP connection to controller succeed. @@ -516,8 +506,7 @@ class OFSwitch13Device : public Object * \param pkt The BOFUSS packet. * \param entry The meter entry that dropped the packet. */ - void NotifyPacketDroppedByMeter(struct packet* pkt, - struct meter_entry* entry); + void NotifyPacketDroppedByMeter(struct packet* pkt, struct meter_entry* entry); /** * Notify this device of an unmatched packet dropped by OpenFlow flow table @@ -525,20 +514,20 @@ class OFSwitch13Device : public Object * \param pkt The BOFUSS packet. * \param table The flow table that dropped the packet. */ - void NotifyPacketDroppedByTable(struct packet* pkt, - struct flow_table* table); + void NotifyPacketDroppedByTable(struct packet* pkt, struct flow_table* table); /** * Notify this device of a packet saved into buffer. This method will get - * the ns-3 packet in pipeline and save into buffer map. \param packetId The - * ns-3 packet id. \param timeout The buffer timeout. + * the ns-3 packet in pipeline and save into buffer map. + * \param packetId The ns-3 packet id. + * \param timeout The buffer timeout. */ - void BufferPacketSave(uint64_t packetId, time_t timeout); + void BufferPacketSave(uint64_t packetId, uint64_t timeout); /** * Notify this device of a packet retrieved from buffer. This method will - * get the ns-3 packet from buffer map and put it back into pipeline. \param - * packetId The ns-3 packet id. + * get the ns-3 packet from buffer map and put it back into pipeline. + * \param packetId The ns-3 packet id. */ void BufferPacketRetrieve(uint64_t packetId); @@ -553,29 +542,26 @@ class OFSwitch13Device : public Object * \param socket The connection socket. * \return The remote controller. */ - Ptr GetRemoteController( - Ptr socket); + Ptr GetRemoteController(Ptr socket); /** * Get the remote controller for this address. * \param address The socket address. * \return The remote controller. */ - Ptr GetRemoteController( - Address address); + Ptr GetRemoteController(Address address); /** * Get the remote controller for this BOFUSS remote pointer. * \param remote The BOFUSS remote pointer. * \return The remote controller. */ - Ptr GetRemoteController( - struct remote* remote); + Ptr GetRemoteController(struct remote* remote); /** * Increase the global packet ID counter and return a new packet ID. This ID - * is different from the internal ns3::Packet::GetUid (), as we need an - * unique value even for fragmented or brodcast packets. Its usage is + * is different from the internal ns3::Packet::GetUid(), as we need an + * unique value even for fragmented or broadcast packets. Its usage is * restricted to this device. * \return New unique ID for this packet. */ diff --git a/model/ofswitch13-interface.cc b/model/ofswitch13-interface.cc index 2a037fb..49ed5de 100644 --- a/model/ofswitch13-interface.cc +++ b/model/ofswitch13-interface.cc @@ -133,10 +133,7 @@ time_msec(void) /** Overriding BOFUSS weak functions using static member functions. */ void -send_packet_to_controller(struct pipeline* pl, - struct packet* pkt, - uint8_t table_id, - uint8_t reason) +send_packet_to_controller(struct pipeline* pl, struct packet* pkt, uint8_t table_id, uint8_t reason) { return OFSwitch13Device::SendPacketToController(pl, pkt, table_id, reason); } @@ -154,11 +151,7 @@ dp_actions_output_port(struct packet* pkt, uint16_t max_len, uint64_t cookie) { - OFSwitch13Device::DpActionsOutputPort(pkt, - out_port, - out_queue, - max_len, - cookie); + OFSwitch13Device::DpActionsOutputPort(pkt, out_port, out_queue, max_len, cookie); } void @@ -172,7 +165,7 @@ dpctl_transact_and_print(struct vconn* vconn, struct ofl_msg_header* req, struct ofl_msg_header** repl) { - // Different from bofus dpctl, this transaction doesn't wait for a reply, + // Different from BOFUSS dpctl, this transaction doesn't wait for a reply, // as ns-3 socket library doesn't provide blocking sockets. So, we send the // request and return. The reply will came later, using the ns-3 callback // mechanism. diff --git a/model/ofswitch13-interface.h b/model/ofswitch13-interface.h index 9cfb71b..f39ee1a 100644 --- a/model/ofswitch13-interface.h +++ b/model/ofswitch13-interface.h @@ -60,8 +60,8 @@ extern "C" #include #include #include -#include #include +#include #include #include #include @@ -81,10 +81,9 @@ typedef void (*OpenFlowCallback)(Ptr packet); /** * \ingroup ofswitch13 - * Enable the logging system of the BOFUSS library. - * By default, it will configure de logging system for maximum verbose dump on - * console. You can set the \p printToFile parameter to dump messages to file - * instead. + * Enable the logging system of the BOFUSS library. By default, it will + * configure de logging system for maximum verbose dump on console. You can set + * the \p printToFile parameter to dump messages to file instead. * \param printToFile Dump log messages to file instead of console. * \param prefix Filename prefix to use for log files. * \param explicitFilename Treat the prefix as an explicit filename if true. @@ -97,17 +96,15 @@ void EnableBofussLog(bool printToFile = false, /** * \ingroup ofswitch13 - * Create an internal BOFUSS buffer from ns3::Packet. Takes a - * Ptr and generates a buffer (struct ofpbuf*) from it, loading the - * packet data as well as its headers into the buffer. + * Create an internal BOFUSS buffer from ns3::Packet. Takes a Ptr and + * generates a buffer (struct ofpbuf*) from it, loading the packet data as well + * as its headers into the buffer. * \param packet The ns-3 packet. * \param bodyRoom The size to allocate for data. - * \param headRoom The size to allocate for headers (left unitialized). + * \param headRoom The size to allocate for headers (left uninitialized). * \return The OpenFlow Buffer created from the packet. */ -struct ofpbuf* BufferFromPacket(Ptr packet, - size_t bodyRoom, - size_t headRoom = 0); +struct ofpbuf* BufferFromPacket(Ptr packet, size_t bodyRoom, size_t headRoom = 0); /** * \ingroup ofswitch13 @@ -122,9 +119,9 @@ Ptr PacketFromMsg(struct ofl_msg_header* msg, uint32_t xid = 0); /** * \ingroup ofswitch13 - * Create a new ns3::Packet from internal BOFUSS buffer. Takes a buffer - * (struct ofpbuf*) and generates a Ptr from it, load the data as well - * as its headers into the packet. + * Create a new ns3::Packet from internal BOFUSS buffer. Takes a buffer (struct + * ofpbuf*) and generates a Ptr from it, load the data as well as its + * headers into the packet. * \param buffer The internal buffer. * \return The ns3::Packet created. */ diff --git a/model/ofswitch13-learning-controller.cc b/model/ofswitch13-learning-controller.cc index 7ab1456..6e176de 100644 --- a/model/ofswitch13-learning-controller.cc +++ b/model/ofswitch13-learning-controller.cc @@ -71,9 +71,7 @@ OFSwitch13LearningController::HandlePacketIn(struct ofl_msg_packet_in* msg, // Get the switch datapath ID uint64_t swDpId = swtch->GetDpId(); - char* msgStr = - ofl_structs_match_to_string((struct ofl_match_header*)msg->match, - nullptr); + char* msgStr = ofl_structs_match_to_string((struct ofl_match_header*)msg->match, nullptr); NS_LOG_DEBUG("Packet in match: " << msgStr); free(msgStr); @@ -129,24 +127,25 @@ OFSwitch13LearningController::HandlePacketIn(struct ofl_msg_packet_in* msg, } else { - NS_LOG_DEBUG("Learning that mac " - << src48 << " can be found at port " - << inPort); + NS_LOG_DEBUG("Learning mac " << src48 << " at port " << inPort); // Send a flow-mod to switch creating this flow. Let's // configure the flow entry to 10s idle timeout and to // notify the controller when flow expires. (flags=0x0001) + + // clang-format off std::ostringstream cmd; cmd << "flow-mod cmd=add,table=0,idle=10,flags=0x0001" - << ",prio=" << ++prio << " eth_dst=" << src48 + << ",prio=" << ++prio + << " eth_dst=" << src48 << " apply:output=" << inPort; + // clang-format on DpctlExecute(swDpId, cmd.str()); } } else { - NS_ASSERT_MSG(itSrc->second == inPort, - "Inconsistent L2 switching table"); + NS_ASSERT_MSG(itSrc->second == inPort, "Inconsistent L2 switching table"); } } else @@ -170,8 +169,8 @@ OFSwitch13LearningController::HandlePacketIn(struct ofl_msg_packet_in* msg, } // Create output action - struct ofl_action_output* a = (struct ofl_action_output*)xmalloc( - sizeof(struct ofl_action_output)); + struct ofl_action_output* a = + (struct ofl_action_output*)xmalloc(sizeof(struct ofl_action_output)); a->header.type = OFPAT_OUTPUT; a->port = outPort; a->max_len = 0; @@ -184,7 +183,7 @@ OFSwitch13LearningController::HandlePacketIn(struct ofl_msg_packet_in* msg, } else { - NS_LOG_WARN("This controller can't handle the packet. Unkwnon reason."); + NS_LOG_WARN("This controller can't handle the packet. Unknown reason."); } // All handlers must free the message when everything is ok @@ -193,10 +192,9 @@ OFSwitch13LearningController::HandlePacketIn(struct ofl_msg_packet_in* msg, } ofl_err -OFSwitch13LearningController::HandleFlowRemoved( - struct ofl_msg_flow_removed* msg, - Ptr swtch, - uint32_t xid) +OFSwitch13LearningController::HandleFlowRemoved(struct ofl_msg_flow_removed* msg, + Ptr swtch, + uint32_t xid) { NS_LOG_FUNCTION(this << swtch << xid); @@ -209,8 +207,7 @@ OFSwitch13LearningController::HandleFlowRemoved( { Mac48Address mac48; struct ofl_match_tlv* ethSrc = - oxm_match_lookup(OXM_OF_ETH_DST, - (struct ofl_match*)msg->stats->match); + oxm_match_lookup(OXM_OF_ETH_DST, (struct ofl_match*)msg->stats->match); mac48.CopyFrom(ethSrc->value); L2Table_t* l2Table = &it->second; @@ -235,12 +232,10 @@ OFSwitch13LearningController::HandshakeSuccessful(Ptr swtch) // Get the switch datapath ID uint64_t swDpId = swtch->GetDpId(); - // After a successfull handshake, let's install the table-miss entry, - // setting to 128 bytes the maximum amount of data from a packet that should - // be sent to the controller. - DpctlExecute(swDpId, - "flow-mod cmd=add,table=0,prio=0 " - "apply:output=ctrl:128"); + // After a successful handshake, let's install the table-miss entry, setting + // to 128 bytes the maximum amount of data from a packet that should be sent + // to the controller. + DpctlExecute(swDpId, "flow-mod cmd=add,table=0,prio=0 apply:output=ctrl:128"); // Configure te switch to buffer packets and send only the first 128 bytes // of each packet sent to the controller when not using an output action to diff --git a/model/ofswitch13-learning-controller.h b/model/ofswitch13-learning-controller.h index 01834d8..455f5e0 100644 --- a/model/ofswitch13-learning-controller.h +++ b/model/ofswitch13-learning-controller.h @@ -48,7 +48,6 @@ class OFSwitch13LearningController : public OFSwitch13Controller * Handle packet-in messages sent from switch to this controller. Look for * L2 switching information, update the structures and send a packet-out * back. - * * \param msg The packet-in message. * \param swtch The switch information. * \param xid Transaction id. @@ -61,7 +60,6 @@ class OFSwitch13LearningController : public OFSwitch13Controller /** * Handle flow removed messages sent from switch to this controller. Look * for L2 switching information and removes associated entry. - * * \param msg The flow removed message. * \param swtch The switch information. * \param xid Transaction id. @@ -90,7 +88,7 @@ class OFSwitch13LearningController : public OFSwitch13Controller /** Map datapathID to L2SwitchingTable */ typedef std::map DatapathMap_t; - /** Switching information for all dapataths */ + /** Switching information for every datapath */ DatapathMap_t m_learnedInfo; //\} }; diff --git a/model/ofswitch13-port.cc b/model/ofswitch13-port.cc index edbfc40..2869404 100644 --- a/model/ofswitch13-port.cc +++ b/model/ofswitch13-port.cc @@ -30,8 +30,7 @@ #include #undef NS_LOG_APPEND_CONTEXT -#define NS_LOG_APPEND_CONTEXT \ - std::clog << "[dp " << m_dpId << " port " << m_portNo << "] "; +#define NS_LOG_APPEND_CONTEXT std::clog << "[dp " << m_dpId << " port " << m_portNo << "] "; namespace ns3 { @@ -88,30 +87,26 @@ OFSwitch13Port::GetTypeId() .SetParent() .SetGroupName("OFSwitch13") .AddConstructor() - .AddAttribute( - "PortQueue", - "The OpenFlow queue to use as the TX queue in this port.", - PointerValue(), - MakePointerAccessor(&OFSwitch13Port::m_portQueue), - MakePointerChecker()) - .AddAttribute( - "QueueFactory", - "The object factory for the OpenFlow queue.", - TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, - ObjectFactoryValue(GetDefaultQueueFactory()), - MakeObjectFactoryAccessor(&OFSwitch13Port::m_factQueue), - MakeObjectFactoryChecker()) - - .AddTraceSource( - "SwitchPortRx", - "Trace source indicating a packet received at this port.", - MakeTraceSourceAccessor(&OFSwitch13Port::m_rxTrace), - "ns3::Packet::TracedCallback") - .AddTraceSource( - "SwitchPortTx", - "Trace source indicating a packet sent at this port.", - MakeTraceSourceAccessor(&OFSwitch13Port::m_txTrace), - "ns3::Packet::TracedCallback"); + .AddAttribute("PortQueue", + "The OpenFlow queue to use as the TX queue in this port.", + PointerValue(), + MakePointerAccessor(&OFSwitch13Port::m_portQueue), + MakePointerChecker()) + .AddAttribute("QueueFactory", + "The object factory for the OpenFlow queue.", + TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, + ObjectFactoryValue(GetDefaultQueueFactory()), + MakeObjectFactoryAccessor(&OFSwitch13Port::m_factQueue), + MakeObjectFactoryChecker()) + + .AddTraceSource("SwitchPortRx", + "Trace source indicating a packet received at this port.", + MakeTraceSourceAccessor(&OFSwitch13Port::m_rxTrace), + "ns3::Packet::TracedCallback") + .AddTraceSource("SwitchPortTx", + "Trace source indicating a packet sent at this port.", + MakeTraceSourceAccessor(&OFSwitch13Port::m_txTrace), + "ns3::Packet::TracedCallback"); return tid; } @@ -143,8 +138,7 @@ OFSwitch13Port::NotifyConstructionCompleted() // Check for valid NetDevice type Ptr csmaDev = m_netDev->GetObject(); Ptr virtDev = m_netDev->GetObject(); - NS_ABORT_MSG_IF(!csmaDev && !virtDev, - "NetDevice must be CsmaNetDevice or VirtualNetDevice."); + NS_ABORT_MSG_IF(!csmaDev && !virtDev, "NetDevice must be CsmaNetDevice or VirtualNetDevice."); // Filling BOFUSS internal structures for this port. size_t oflPortSize = sizeof(struct ofl_port); @@ -173,8 +167,8 @@ OFSwitch13Port::NotifyConstructionCompleted() m_swPort->flags |= SWP_USED; // To avoid a null check failure in BOFUSS - // dp_ports_handle_stats_request_port (), we are pointing m_swPort->netdev - // to corresponding ns3::NetDevice, but this pointer must not be used! + // dp_ports_handle_stats_request_port(), we are pointing m_swPort->netdev to + // corresponding ns3::NetDevice, but this pointer must not be used! m_swPort->netdev = (struct netdev*)PeekPointer(m_netDev); // Creating the OFSwitch13Queue for this switch port @@ -203,14 +197,12 @@ OFSwitch13Port::NotifyConstructionCompleted() // Register the receive callback to get packets from the NetDevice. if (csmaDev) { - csmaDev->SetOpenFlowReceiveCallback( - MakeCallback(&OFSwitch13Port::Receive, this)); + csmaDev->SetOpenFlowReceiveCallback(MakeCallback(&OFSwitch13Port::Receive, this)); } else { NS_ASSERT(virtDev); - virtDev->SetOpenFlowReceiveCallback( - MakeCallback(&OFSwitch13Port::Receive, this)); + virtDev->SetOpenFlowReceiveCallback(MakeCallback(&OFSwitch13Port::Receive, this)); } } @@ -335,7 +327,7 @@ OFSwitch13Port::Receive(Ptr device, // Check port configuration. if ((m_swPort->conf->config & (OFPPC_NO_RECV | OFPPC_PORT_DOWN)) != 0) { - NS_LOG_WARN("This port is down or inoperating. Discarding packet"); + NS_LOG_WARN("This port is down or inoperative. Discarding packet"); return false; } @@ -361,9 +353,7 @@ OFSwitch13Port::Receive(Ptr device, } bool -OFSwitch13Port::Send(Ptr packet, - uint32_t queueNo, - uint64_t tunnelId) +OFSwitch13Port::Send(Ptr packet, uint32_t queueNo, uint64_t tunnelId) { NS_LOG_FUNCTION(this << packet << queueNo << tunnelId); @@ -377,8 +367,7 @@ OFSwitch13Port::Send(Ptr packet, m_txTrace(packet); Ptr packetCopy = packet->Copy(); - NS_LOG_DEBUG("Pkt " << packetCopy->GetUid() - << " will be sent at this port."); + NS_LOG_DEBUG("Pkt " << packetCopy->GetUid() << " will be sent at this port."); // Removing the Ethernet header and trailer from packet, which will be // included again by CsmaNetDevice diff --git a/model/ofswitch13-port.h b/model/ofswitch13-port.h index c30ab4d..f3c3a66 100644 --- a/model/ofswitch13-port.h +++ b/model/ofswitch13-port.h @@ -40,12 +40,12 @@ class OFSwitch13Device; /** * \ingroup ofswitch13 * - * A OpenFlow switch port, interconnecting the underlying NetDevice to the - * OpenFlow device through the OpenFlow receive callback. This class handles - * the BOFUSS internal sw_port structure. + * A OpenFlow switch port to interconnect the underlying NetDevice to the + * OpenFlow device through the OpenFlow receive callback. This class handles the + * BOFUSS internal sw_port structure. * \see BOFUSS udatapath/dp_ports.h - * \attention Each underlying NetDevice used as port must only be assigned - * a MAC Address. Adding an Ipv4/IPv6 layer to it may cause error. + * \attention Each underlying NetDevice used as port must only be assigned a MAC + * Address. Adding an Ipv4/IPv6 layer to it may cause error. */ class OFSwitch13Port : public Object { @@ -56,14 +56,12 @@ class OFSwitch13Port : public Object /** * Complete Constructor. Create and populate a new datapath port, notifying * the controller of this new port. - * \see ofsoftswitch new_port () at udatapath/dp_ports.c + * \see BOFUSS new_port() at udatapath/dp_ports.c * \param dp The datapath. * \param netDev The underlying NetDevice. * \param openflowDev The OpenFlow device. */ - OFSwitch13Port(struct datapath* dp, - Ptr netDev, - Ptr openflowDev); + OFSwitch13Port(struct datapath* dp, Ptr netDev, Ptr openflowDev); /** * Register this type. @@ -112,15 +110,13 @@ class OFSwitch13Port : public Object * Send a packet over this OpenFlow switch port. It will check port * configuration, update counters and send the packet to the underlying * device. - * \see BOFUSS function dp_ports_run () at udatapath/dp_ports.c + * \see BOFUSS function dp_ports_run() at udatapath/dp_ports.c * \param packet The Packet to send. * \param queueNo The queue to use. * \param tunnelId The metadata associated with a logical port. * \return true if the packet was sent successfully, false otherwise. */ - bool Send(Ptr packet, - uint32_t queueNo = 0, - uint64_t tunnelId = 0); + bool Send(Ptr packet, uint32_t queueNo = 0, uint64_t tunnelId = 0); protected: /** Destructor implementation */ @@ -132,7 +128,7 @@ class OFSwitch13Port : public Object private: /** * Create the bitmaps of OFPPF_* describing port features. - * \see ofsoftswitch netdev_get_features () at lib/netdev.c + * \see BOFUSS netdev_get_features() at lib/netdev.c * \return Port features bitmap. */ uint32_t GetPortFeatures(); @@ -141,11 +137,11 @@ class OFSwitch13Port : public Object * Called when a packet is received on this OpenFlow switch port by the * underlying NetDevice. It will check port configuration, update counter * and send the packet to the OpenFlow pipeline. - * \see BOFUSS function dp_ports_run () at udatapath/dp_ports.c + * \see BOFUSS function dp_ports_run() at udatapath/dp_ports.c * \param device Underlying ns-3 network device. * \param packet The received packet. * \param protocol Next protocol header value. - * \param from Address of the correspondant. + * \param from Address of the correspondent. * \param to Address of the destination. * \param packetType Type of the packet. * \return true. diff --git a/model/ofswitch13-priority-queue.cc b/model/ofswitch13-priority-queue.cc index 473dba4..961cd5c 100644 --- a/model/ofswitch13-priority-queue.cc +++ b/model/ofswitch13-priority-queue.cc @@ -23,8 +23,7 @@ #include "ns3/string.h" #undef NS_LOG_APPEND_CONTEXT -#define NS_LOG_APPEND_CONTEXT \ - std::clog << "[dp " << m_dpId << " port " << m_portNo << "] "; +#define NS_LOG_APPEND_CONTEXT std::clog << "[dp " << m_dpId << " port " << m_portNo << "] "; namespace ns3 { @@ -50,19 +49,17 @@ OFSwitch13PriorityQueue::GetTypeId() .SetParent() .SetGroupName("OFSwitch13") .AddConstructor() - .AddAttribute( - "NumQueues", - "The number of internal priority queues.", - TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, - UintegerValue(1), - MakeUintegerAccessor(&OFSwitch13PriorityQueue::m_numQueues), - MakeUintegerChecker(1, PORT_MAX_QUEUES)) + .AddAttribute("NumQueues", + "The number of internal priority queues.", + TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, + UintegerValue(1), + MakeUintegerAccessor(&OFSwitch13PriorityQueue::m_numQueues), + MakeUintegerChecker(1, PORT_MAX_QUEUES)) .AddAttribute("QueueFactory", "The object factory for internal priority queues.", TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, ObjectFactoryValue(GetDefaultQueueFactory()), - MakeObjectFactoryAccessor( - &OFSwitch13PriorityQueue::m_facQueues), + MakeObjectFactoryAccessor(&OFSwitch13PriorityQueue::m_facQueues), MakeObjectFactoryChecker()); return tid; } diff --git a/model/ofswitch13-priority-queue.h b/model/ofswitch13-priority-queue.h index bc806e6..62c8ff1 100644 --- a/model/ofswitch13-priority-queue.h +++ b/model/ofswitch13-priority-queue.h @@ -31,9 +31,9 @@ extern template class Queue; /** * \ingroup ofswitch13 * - * This class implements the priority queuing discipline for OpenFlow queue. - * It creates a collection of N priority queues, identified by IDs ranging from - * 0 to N-1 with decreasing priority (queue ID 0 has the highest priority). The + * This class implements the priority queuing discipline for OpenFlow queue. It + * creates a collection of N priority queues, identified by IDs ranging from 0 + * to N-1 with decreasing priority (queue ID 0 has the highest priority). The * output scheduling algorithm ensures that higher-priority queues are always * served first. */ diff --git a/model/ofswitch13-queue.cc b/model/ofswitch13-queue.cc index e3b8f15..4cd1f39 100644 --- a/model/ofswitch13-queue.cc +++ b/model/ofswitch13-queue.cc @@ -26,8 +26,7 @@ #include "ns3/string.h" #undef NS_LOG_APPEND_CONTEXT -#define NS_LOG_APPEND_CONTEXT \ - std::clog << "[dp " << m_dpId << " port " << m_portNo << "] "; +#define NS_LOG_APPEND_CONTEXT std::clog << "[dp " << m_dpId << " port " << m_portNo << "] "; namespace ns3 { @@ -38,15 +37,14 @@ NS_OBJECT_ENSURE_REGISTERED(OFSwitch13Queue); TypeId OFSwitch13Queue::GetTypeId() { - static TypeId tid = - TypeId("ns3::OFSwitch13Queue") - .SetParent>() - .SetGroupName("OFSwitch13") - .AddAttribute("QueueList", - "The list of internal queues.", - ObjectVectorValue(), - MakeObjectVectorAccessor(&OFSwitch13Queue::m_queues), - MakeObjectVectorChecker>()); + static TypeId tid = TypeId("ns3::OFSwitch13Queue") + .SetParent>() + .SetGroupName("OFSwitch13") + .AddAttribute("QueueList", + "The list of internal queues.", + ObjectVectorValue(), + MakeObjectVectorAccessor(&OFSwitch13Queue::m_queues), + MakeObjectVectorChecker>()); return tid; } @@ -86,9 +84,9 @@ OFSwitch13Queue::Enqueue(Ptr packet) swQueue->stats->tx_packets++; swQueue->stats->tx_bytes += packet->GetSize(); - // Enqueue the packet in this queue too. - // This is necessary to ensure consistent statistics. Otherwise, when - // the NetDevice calls the IsEmpty () method, it will return true. + // Enqueue the packet in this queue too. This is necessary to ensure + // consistent statistics. Otherwise, when the NetDevice calls the + // IsEmpty() method, it will return true. DoEnqueue(GetContainer().end(), packet); } else @@ -96,8 +94,8 @@ OFSwitch13Queue::Enqueue(Ptr packet) NS_LOG_DEBUG("Packet enqueue dropped by internal queue " << queueId); swQueue->stats->tx_errors++; - // Drop the packet in this queue too. - // This is necessary to ensure consistent statistics. + // Drop the packet in this queue too. This is necessary to ensure + // consistent statistics. DropBeforeEnqueue(packet); } return retval; @@ -130,8 +128,8 @@ OFSwitch13Queue::DoDispose() { NS_LOG_FUNCTION(this); - // While m_swPort is valid, free internal stats and props - // structures for each available queue + // While m_swPort is valid, free internal stats and props structures for + // each available queue if (m_swPort) { struct sw_queue* swQueue; @@ -189,6 +187,17 @@ OFSwitch13Queue::AddQueue(Ptr> queue) m_queues.emplace_back(queue); NS_LOG_DEBUG("New queue with ID " << queueId); + // Update the size of this queue. + uint32_t maxSizeValue = 0; + QueueSizeUnit maxSizeUnit = m_queues.at(0)->GetMaxSize().GetUnit(); + for (const auto& queueIt : m_queues) + { + NS_ASSERT_MSG(queueIt->GetMaxSize().GetUnit() == maxSizeUnit, + "Be consistent with queues operation modes."); + maxSizeValue += queueIt->GetMaxSize().GetValue(); + } + SetMaxSize(QueueSize(maxSizeUnit, maxSizeValue)); + return queueId; } @@ -197,8 +206,8 @@ OFSwitch13Queue::NotifyDequeue(Ptr packet) { NS_LOG_FUNCTION(this << packet); - // Dequeue the packet from this queue too. As we don't know the - // exactly packet location on this queue, we have to look for it. + // Dequeue the packet from this queue too. As we don't know the exactly + // packet location on this queue, we have to look for it. for (auto it = GetContainer().begin(); it != GetContainer().end(); it++) { if ((*it) == packet) @@ -215,8 +224,8 @@ OFSwitch13Queue::NotifyRemove(Ptr packet) { NS_LOG_FUNCTION(this << packet); - // Remove the packet from this queue too. As we don't know the - // exactly packet location on this queue, we have to look for it. + // Remove the packet from this queue too. As we don't know the exactly + // packet location on this queue, we have to look for it. for (auto it = GetContainer().begin(); it != GetContainer().end(); it++) { if ((*it) == packet) diff --git a/model/ofswitch13-queue.h b/model/ofswitch13-queue.h index af422b9..d6a290d 100644 --- a/model/ofswitch13-queue.h +++ b/model/ofswitch13-queue.h @@ -38,18 +38,18 @@ extern template class Queue; * An OpenFlow switch provides limited Quality-of-Service support (QoS) through * a simple queuing mechanism. One (or more) queues can attach to a port and be * used to map flow entries on it. Flow entries mapped to a specific queue will - * be treated according to that queue's configuration. Queue configuration - * takes place outside the OpenFlow protocol. + * be treated according to that queue's configuration. Queue configuration takes + * place outside the OpenFlow protocol. * * This class implements the queue interface, extending the ns3::Queue * class to allow compatibility with the CsmaNetDevice used by OFSwitch13Port. * Internally, it holds a collection of N (possibly different) queues, - * identified by IDs ranging from 0 to N-1. The Enqueue () method uses the + * identified by IDs ranging from 0 to N-1. The Enqueue() method uses the * ns3::QueueTag to identify which internal queue will hold the packet. - * Subclasses can perform different output scheduling algorithms by - * implementing the Dequeue (), Remove () and Peek () methods, always calling - * the NotifyDequeue () and NotifyRemoved () methods from this base class to - * keep consistency. + * Subclasses can perform different output scheduling algorithms by implementing + * the Dequeue(), Remove() and Peek() methods, always calling the + * NotifyDequeue() and NotifyRemoved() methods from this base class to keep + * consistency. */ class OFSwitch13Queue : public Queue { @@ -77,7 +77,7 @@ class OFSwitch13Queue : public Queue * \param queueId The queue id. * \return The queue pointer. * \internal This function is marked as const to allow its usage inside - * DoPeek () member function. + * DoPeek() member function. */ Ptr> GetQueue(int queueId) const; @@ -118,8 +118,7 @@ class OFSwitch13Queue : public Queue uint32_t m_portNo; //!< OpenFlow port number. private: - /** Structure to save the list of internal queues in this queue interface. - */ + /** Structure to save the list of internal queues in this interface. */ typedef std::vector> QueueList_t; struct sw_port* m_swPort; //!< BOFUSS port structure. diff --git a/model/ofswitch13-socket-handler.cc b/model/ofswitch13-socket-handler.cc index a6c0dd3..ea1d1d8 100644 --- a/model/ofswitch13-socket-handler.cc +++ b/model/ofswitch13-socket-handler.cc @@ -28,10 +28,12 @@ NS_OBJECT_ENSURE_REGISTERED(OFSwitch13SocketHandler); TypeId OFSwitch13SocketHandler::GetTypeId() { + // clang-format off static TypeId tid = TypeId("ns3::OFSwitch13SocketHandler") .SetParent() .SetGroupName("OFSwitch13"); return tid; + // clang-format on } OFSwitch13SocketHandler::OFSwitch13SocketHandler(Ptr socket) diff --git a/model/ofswitch13-socket-handler.h b/model/ofswitch13-socket-handler.h index e7b1a78..97d124e 100644 --- a/model/ofswitch13-socket-handler.h +++ b/model/ofswitch13-socket-handler.h @@ -34,15 +34,15 @@ namespace ns3 /** * \ingroup ofswitch13 - * Class used to read/send single OpenFlow message from/to an open socket. - * The TCP socket receive callback is connected to the Recv () method, which is + * Class used to read/send single OpenFlow message from/to an open socket. The + * TCP socket receive callback is connected to the Recv() method, which is * responsible for reading the correct number of bytes of a complete OpenFlow * message. When the OpenFlow message is completely received, it is sent to the - * connected callback that was previously set using the SetReceiveCallback () + * connected callback that was previously set using the SetReceiveCallback() * method. On the other direction, the TCP socket send callback is connected to - * the Send () method that forwards OpenFlow message received by the - * SendMessage () method to the open socket, respecting the original order of - * the messages. + * the Send() method that forwards OpenFlow message received by the + * SendMessage() method to the open socket, respecting the original order of the + * messages. */ class OFSwitch13SocketHandler : public Object { diff --git a/utils/csma-full-duplex-3_38.patch b/utils/csma-full-duplex-3_38.patch index 90f9647..1127b84 100644 --- a/utils/csma-full-duplex-3_38.patch +++ b/utils/csma-full-duplex-3_38.patch @@ -1,11 +1,21 @@ -commit b554673c2f54e3c703545ac65316b854bf5378b4 -Author: Luciano Jerez Chaves -Date: Fri Mar 31 12:17:46 2023 -0300 +From 8110d79c7bb6e9f67d271e1bdda09e55c92ef107 Mon Sep 17 00:00:00 2001 +From: Luciano J Chaves +Date: Fri, 1 Sep 2023 09:24:38 -0300 +Subject: [PATCH] CSMA full-duplex patch - CSMA full-duplex patch. +--- + src/csma/doc/csma.rst | 62 +++++++++----- + src/csma/examples/CMakeLists.txt | 1 + + src/csma/examples/csma-duplex.cc | 105 +++++++++++++++++++++++ + src/csma/model/csma-channel.cc | 133 +++++++++++++++++++++++------- + src/csma/model/csma-channel.h | 112 ++++++++++++++++++++++--- + src/csma/model/csma-net-device.cc | 80 +++++++++++------- + src/csma/test/examples-to-run.py | 1 + + 7 files changed, 401 insertions(+), 93 deletions(-) + create mode 100644 src/csma/examples/csma-duplex.cc diff --git a/src/csma/doc/csma.rst b/src/csma/doc/csma.rst -index 13cc3c876..e2c444ad5 100644 +index 13cc3c876..c4f59ce47 100644 --- a/src/csma/doc/csma.rst +++ b/src/csma/doc/csma.rst @@ -14,6 +14,12 @@ The |ns3| CSMA device models a simple bus network in the spirit of Ethernet. @@ -16,7 +26,7 @@ index 13cc3c876..e2c444ad5 100644 +communication restricts a node to either transmit or receive at a time but not +perform both actions concurrently. By default, the |ns3| CSMA device models a +half-duplex bus network, with no fixed limit on the number of devices connected -+to the shared transmission medium. ++to the shared transmission medium. + Typically when one thinks of a bus network Ethernet or IEEE 802.3 comes to mind. Ethernet uses CSMA/CD (Carrier Sense Multiple Access with Collision Detection @@ -136,10 +146,10 @@ index 6bf85da2a..201fa9d3d 100644 example diff --git a/src/csma/examples/csma-duplex.cc b/src/csma/examples/csma-duplex.cc new file mode 100644 -index 000000000..7d65f1096 +index 000000000..c9a3a3f2b --- /dev/null +++ b/src/csma/examples/csma-duplex.cc -@@ -0,0 +1,103 @@ +@@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017 Luciano Jerez Chaves + * @@ -219,13 +229,15 @@ index 000000000..7d65f1096 + + // TCP traffic from host 0 to 1 + BulkSendHelper sender0("ns3::TcpSocketFactory", InetSocketAddress(h1Addr, 10000)); -+ PacketSinkHelper sink1("ns3::TcpSocketFactory", InetSocketAddress(Ipv4Address::GetAny(), 10000)); ++ PacketSinkHelper sink1("ns3::TcpSocketFactory", ++ InetSocketAddress(Ipv4Address::GetAny(), 10000)); + senderApps.Add(sender0.Install(hosts.Get(0))); + sinkApps.Add(sink1.Install(hosts.Get(1))); + + // TCP traffic from host 1 to 0 + BulkSendHelper sender1("ns3::TcpSocketFactory", InetSocketAddress(h0Addr, 10001)); -+ PacketSinkHelper sink0("ns3::TcpSocketFactory", InetSocketAddress(Ipv4Address::GetAny(), 10001)); ++ PacketSinkHelper sink0("ns3::TcpSocketFactory", ++ InetSocketAddress(Ipv4Address::GetAny(), 10001)); + senderApps.Add(sender1.Install(hosts.Get(1))); + sinkApps.Add(sink0.Install(hosts.Get(0))); + @@ -244,7 +256,7 @@ index 000000000..7d65f1096 + std::cout << "Total bytes sent from H1 to H0: " << pktSink0->GetTotalRx() << std::endl; +} diff --git a/src/csma/model/csma-channel.cc b/src/csma/model/csma-channel.cc -index 9f1fad3ce..fca9721cf 100644 +index 9f1fad3ce..2563bd662 100644 --- a/src/csma/model/csma-channel.cc +++ b/src/csma/model/csma-channel.cc @@ -1,5 +1,8 @@ @@ -457,13 +469,11 @@ index 9f1fad3ce..fca9721cf 100644 { return false; } -@@ -332,10 +377,10 @@ CsmaChannel::GetDelay() - return m_delay; +@@ -333,9 +378,9 @@ CsmaChannel::GetDelay() } --WireState + WireState -CsmaChannel::GetState() -+CsmaChannel::WireState +CsmaChannel::GetState(uint32_t deviceId) { - return m_state; @@ -500,7 +510,7 @@ index 9f1fad3ce..fca9721cf 100644 +} + +void -+CsmaChannel::SetState(uint32_t deviceId, CsmaChannel::WireState state) ++CsmaChannel::SetState(uint32_t deviceId, WireState state) +{ + m_state[m_fullDuplex ? deviceId : 0] = state; +} @@ -509,7 +519,7 @@ index 9f1fad3ce..fca9721cf 100644 { active = false; diff --git a/src/csma/model/csma-channel.h b/src/csma/model/csma-channel.h -index da4e948da..e3654cf59 100644 +index da4e948da..5d824f073 100644 --- a/src/csma/model/csma-channel.h +++ b/src/csma/model/csma-channel.h @@ -1,5 +1,8 @@ @@ -537,24 +547,7 @@ index da4e948da..e3654cf59 100644 #include "ns3/channel.h" #include "ns3/data-rate.h" #include "ns3/nstime.h" -@@ -68,16 +75,6 @@ class CsmaDeviceRec - bool IsActive() const; - }; - --/** -- * Current state of the channel -- */ --enum WireState --{ -- IDLE, /**< Channel is IDLE, no packet is being transmitted */ -- TRANSMITTING, /**< Channel is BUSY, a packet is being written by a net device */ -- PROPAGATING /**< Channel is BUSY, packet is propagating to all attached net devices */ --}; -- - /** - * \ingroup csma - * \brief Csma Channel. -@@ -86,11 +83,25 @@ enum WireState +@@ -86,7 +93,11 @@ enum WireState * when many nodes are connected to one wire. It uses a single busy * flag to indicate if the channel is currently in use. It does not * take into account the distances between stations or the speed of @@ -567,20 +560,6 @@ index da4e948da..e3654cf59 100644 */ class CsmaChannel : public Channel { - public: -+ /** -+ * Current state of the channel -+ */ -+ enum WireState -+ { -+ IDLE, /**< Channel is IDLE, no packet is being transmitted */ -+ TRANSMITTING, /**< Channel is BUSY, a packet is being written by a net device */ -+ PROPAGATING /**< Channel is BUSY, packet is propagating to all attached net devices */ -+ }; -+ - /** - * \brief Get the type ID. - * \return the object TypeId @@ -201,19 +212,23 @@ class CsmaChannel : public Channel * packet p as the m_currentPkt, the packet being currently * transmitting. @@ -747,7 +726,7 @@ index da4e948da..e3654cf59 100644 } // namespace ns3 diff --git a/src/csma/model/csma-net-device.cc b/src/csma/model/csma-net-device.cc -index e10648f96..647ea50c3 100644 +index e10648f96..c164c1d13 100644 --- a/src/csma/model/csma-net-device.cc +++ b/src/csma/model/csma-net-device.cc @@ -1,5 +1,8 @@ @@ -787,7 +766,7 @@ index e10648f96..647ea50c3 100644 + // Otherwise, we have to wait. // - if (m_channel->GetState() != IDLE) -+ if (m_channel->GetState(m_deviceId) != CsmaChannel::IDLE) ++ if (m_channel->GetState(m_deviceId) != IDLE) { // - // The channel is busy -- backoff and rechedule TransmitStart() unless @@ -844,7 +823,7 @@ index e10648f96..647ea50c3 100644 NS_ASSERT_MSG(m_txMachineState == BUSY, "CsmaNetDevice::transmitCompleteEvent(): Must be BUSY if transmitting"); - NS_ASSERT(m_channel->GetState() == TRANSMITTING); -+ NS_ASSERT(m_channel->GetState(m_deviceId) == CsmaChannel::TRANSMITTING); ++ NS_ASSERT(m_channel->GetState(m_deviceId) == TRANSMITTING); m_txMachineState = GAP; // @@ -924,3 +903,6 @@ index eba7b5b77..b27be27b1 100644 ("csma-multicast", "True", "True"), ("csma-one-subnet", "True", "True"), ("csma-packet-socket", "True", "True"), +-- +2.34.1 + diff --git a/utils/csma-full-duplex-3_39.patch b/utils/csma-full-duplex-3_39.patch new file mode 100644 index 0000000..4d633be --- /dev/null +++ b/utils/csma-full-duplex-3_39.patch @@ -0,0 +1,908 @@ +From 176c16929aa15119f1d5a6b90b5fdfdf7406368d Mon Sep 17 00:00:00 2001 +From: Luciano J Chaves +Date: Fri, 1 Sep 2023 10:00:47 -0300 +Subject: [PATCH] CSMA full-duplex patch + +--- + src/csma/doc/csma.rst | 62 +++++++++----- + src/csma/examples/CMakeLists.txt | 1 + + src/csma/examples/csma-duplex.cc | 105 +++++++++++++++++++++++ + src/csma/model/csma-channel.cc | 133 +++++++++++++++++++++++------- + src/csma/model/csma-channel.h | 112 ++++++++++++++++++++++--- + src/csma/model/csma-net-device.cc | 80 +++++++++++------- + src/csma/test/examples-to-run.py | 1 + + 7 files changed, 401 insertions(+), 93 deletions(-) + create mode 100644 src/csma/examples/csma-duplex.cc + +diff --git a/src/csma/doc/csma.rst b/src/csma/doc/csma.rst +index 13cc3c876..c4f59ce47 100644 +--- a/src/csma/doc/csma.rst ++++ b/src/csma/doc/csma.rst +@@ -14,6 +14,12 @@ The |ns3| CSMA device models a simple bus network in the spirit of Ethernet. + Although it does not model any real physical network you could ever build or + buy, it does provide some very useful functionality. + ++When Ethernet was standardised, all communication was half-duplex. Half-duplex ++communication restricts a node to either transmit or receive at a time but not ++perform both actions concurrently. By default, the |ns3| CSMA device models a ++half-duplex bus network, with no fixed limit on the number of devices connected ++to the shared transmission medium. ++ + Typically when one thinks of a bus network Ethernet or IEEE 802.3 comes to mind. + Ethernet uses CSMA/CD (Carrier Sense Multiple Access with Collision Detection + with exponentially increasing backoff to contend for the shared transmission +@@ -23,6 +29,12 @@ light) carrier sense and priority-based collision "avoidance." Collisions in the + sense of Ethernet never happen and so the |ns3| CSMA device does not model + collision detection, nor will any transmission in progress be "jammed." + ++This model also offers support for full-duplex communication, where the ++transmission medium can operate in both directions simultaneously but is ++restricted to a maximum of two devices connected on the single full-duplex ++link. When in full-duplex operation, the original CSMA/CD protocol is shut off ++and the two devices on the link can send data independently. ++ + CSMA Layer Model + ++++++++++++++++ + +@@ -83,8 +95,7 @@ the protocol stack. + CSMA Channel Model + ****************** + +-The class CsmaChannel models the actual transmission medium. There is no fixed +-limit for the number of devices connected to the channel. The CsmaChannel models ++The class CsmaChannel models the actual transmission medium. The CsmaChannel models + a data rate and a speed-of-light delay which can be accessed via the attributes + "DataRate" and "Delay" respectively. The data rate provided to the channel is + used to set the data rates used by the transmitter sections of the CSMA devices +@@ -94,6 +105,18 @@ limitation (other than by the data type holding the value) on the speed at which + CSMA channels and devices can operate; and no restriction based on any kind of + PHY characteristics. + ++The CsmaChannel can operate in half-duplex or in full-duplex mode, which can be ++defined via the attribute "FullDuplex". The CsmaChannel holds two internal ++subchannels. When operating in half-duplex mode, only the first subchannel is ++used by all devices for both transmission and reception procedures. In this ++case, the CsmaChannel models a broadcast medium so the packet is delivered to ++all of the devices on the channel (except the source) at the end of the ++propagation time. It is the responsibility of the sending device to determine ++whether or not it receives a packet broadcast over the channel. When the ++CsmaChannel is operating in full-duplex mode (with a maximum of two devices ++attached to the channel), each device uses its exclusive subchannel for ++unidirectional packet transmission, getting rid of the CSMA/CD mechanism. ++ + The CsmaChannel has three states, ``IDLE``, ``TRANSMITTING`` and + ``PROPAGATING``. These three states are "seen" instantaneously by all devices on + the channel. By this we mean that if one device begins or ends a simulated +@@ -133,15 +156,11 @@ through its cable to the hub; plus 2) the time it takes for the hub to forward + the packet out a port; plus 3) the time it takes for the signal in question to + propagate to the destination net device. + +-The CsmaChannel models a broadcast medium so the packet is delivered to all of +-the devices on the channel (including the source) at the end of the propagation +-time. It is the responsibility of the sending device to determine whether or not +-it receives a packet broadcast over the channel. +- + The CsmaChannel provides following Attributes: + + * DataRate: The bitrate for packet transmission on connected devices; +-* Delay: The speed of light transmission delay for the channel. ++* Delay: The speed of light transmission delay for the channel; ++* FullDuplex: Whether the channel is operating in full-duplex mode or not. + + CSMA Net Device Model + ********************* +@@ -195,7 +214,9 @@ The CsmaNetDevice implements a random exponential backoff algorithm that is + executed if the channel is determined to be busy (``TRANSMITTING`` or + ``PPROPAGATING``) when the device wants to start propagating. This results in a + random delay of up to pow (2, retries) - 1 microseconds before a retry is +-attempted. The default maximum number of retries is 1000. ++attempted. The default maximum number of retries is 1000. Note that the random ++exponential backoff algorithm is not used when the device is attached to a ++channel in full-duplex operation. + + Using the CsmaNetDevice + *********************** +@@ -349,16 +370,19 @@ net device. + Summary + ******* + +-The ns3 CSMA model is a simplistic model of an Ethernet-like network. It +-supports a Carrier-Sense function and allows for Multiple Access to a +-shared medium. It is not physical in the sense that the state of the +-medium is instantaneously shared among all devices. This means that there +-is no collision detection required in this model and none is implemented. +-There will never be a "jam" of a packet already on the medium. Access to +-the shared channel is on a first-come first-served basis as determined by +-the simulator scheduler. If the channel is determined to be busy by looking +-at the global state, a random exponential backoff is performed and a retry +-is attempted. ++The ns3 CSMA model is a simplistic model of an Ethernet-like network that can ++operate in half-duplex or in full-duplex modes. In half-duplex mode, it ++supports a Carrier-Sense function and allows for Multiple Access to a shared ++medium. It is not physical in the sense that the state of the medium is ++instantaneously shared among all devices. This means that there is no collision ++detection required in this model and none is implemented. There will never be a ++"jam" of a packet already on the medium. Access to the shared channel is on a ++first-come first-served basis as determined by the simulator scheduler. If the ++channel is determined to be busy by looking at the global state, a random ++exponential backoff is performed and a retry is attempted. When operating in ++full-duplex mode, restricted to a maximum of two devices on the channel, the ++transmission medium can operate in both directions simultaneously and there is ++no need of the original CSMA/CD protocol. + + Ns-3 Attributes provide a mechanism for setting various parameters in the + device and channel such as addresses, encapsulation modes and error model +diff --git a/src/csma/examples/CMakeLists.txt b/src/csma/examples/CMakeLists.txt +index 6bf85da2a..201fa9d3d 100644 +--- a/src/csma/examples/CMakeLists.txt ++++ b/src/csma/examples/CMakeLists.txt +@@ -3,6 +3,7 @@ set(base_examples + csma-broadcast + csma-packet-socket + csma-multicast ++ csma-duplex + ) + foreach( + example +diff --git a/src/csma/examples/csma-duplex.cc b/src/csma/examples/csma-duplex.cc +new file mode 100644 +index 000000000..c9a3a3f2b +--- /dev/null ++++ b/src/csma/examples/csma-duplex.cc +@@ -0,0 +1,105 @@ ++/* ++ * Copyright (c) 2017 Luciano Jerez Chaves ++ * ++ * 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 ++ * ++ * Author: Luciano Jerez Chaves ++ */ ++ ++#include "ns3/applications-module.h" ++#include "ns3/core-module.h" ++#include "ns3/csma-module.h" ++#include "ns3/internet-module.h" ++#include "ns3/network-module.h" ++ ++using namespace ns3; ++ ++int ++main(int argc, char* argv[]) ++{ ++ bool verbose = false; ++ bool trace = false; ++ ++ CommandLine cmd; ++ cmd.AddValue("verbose", "Tell application to log if true", verbose); ++ cmd.AddValue("trace", "Tracing traffic to files", trace); ++ cmd.AddValue("duplex", "ns3::CsmaChannel::FullDuplex"); ++ cmd.Parse(argc, argv); ++ ++ if (verbose) ++ { ++ LogComponentEnable("CsmaNetDevice", LOG_LEVEL_ALL); ++ LogComponentEnable("CsmaChannel", LOG_LEVEL_ALL); ++ LogComponentEnable("Backoff", LOG_LEVEL_ALL); ++ } ++ ++ // Create the host nodes ++ NodeContainer hosts; ++ hosts.Create(2); ++ ++ // Connecting the hosts ++ CsmaHelper csmaHelper; ++ csmaHelper.SetChannelAttribute("DataRate", DataRateValue(DataRate("100Mbps"))); ++ csmaHelper.SetChannelAttribute("Delay", TimeValue(MilliSeconds(1))); ++ NetDeviceContainer hostDevices = csmaHelper.Install(hosts); ++ ++ // Enable pcap traces ++ if (trace) ++ { ++ csmaHelper.EnablePcap("csma-duplex", hostDevices); ++ } ++ ++ // Installing the tcp/ip stack into hosts ++ InternetStackHelper internet; ++ internet.Install(hosts); ++ ++ // Set IPv4 host address ++ Ipv4AddressHelper ipv4switches; ++ Ipv4InterfaceContainer internetIpIfaces; ++ ipv4switches.SetBase("10.1.1.0", "255.255.255.0"); ++ internetIpIfaces = ipv4switches.Assign(hostDevices); ++ Ipv4Address h0Addr = internetIpIfaces.GetAddress(0); ++ Ipv4Address h1Addr = internetIpIfaces.GetAddress(1); ++ ++ ApplicationContainer senderApps; ++ ApplicationContainer sinkApps; ++ ++ // TCP traffic from host 0 to 1 ++ BulkSendHelper sender0("ns3::TcpSocketFactory", InetSocketAddress(h1Addr, 10000)); ++ PacketSinkHelper sink1("ns3::TcpSocketFactory", ++ InetSocketAddress(Ipv4Address::GetAny(), 10000)); ++ senderApps.Add(sender0.Install(hosts.Get(0))); ++ sinkApps.Add(sink1.Install(hosts.Get(1))); ++ ++ // TCP traffic from host 1 to 0 ++ BulkSendHelper sender1("ns3::TcpSocketFactory", InetSocketAddress(h0Addr, 10001)); ++ PacketSinkHelper sink0("ns3::TcpSocketFactory", ++ InetSocketAddress(Ipv4Address::GetAny(), 10001)); ++ senderApps.Add(sender1.Install(hosts.Get(1))); ++ sinkApps.Add(sink0.Install(hosts.Get(0))); ++ ++ sinkApps.Start(Seconds(0)); ++ senderApps.Start(Seconds(0.01)); ++ senderApps.Stop(Seconds(5)); ++ ++ // Run the simulation ++ Simulator::Run(); ++ Simulator::Destroy(); ++ ++ // Transmitted bytes ++ Ptr pktSink0 = DynamicCast(sinkApps.Get(1)); ++ Ptr pktSink1 = DynamicCast(sinkApps.Get(0)); ++ std::cout << "Total bytes sent from H0 to H1: " << pktSink1->GetTotalRx() << std::endl; ++ std::cout << "Total bytes sent from H1 to H0: " << pktSink0->GetTotalRx() << std::endl; ++} +diff --git a/src/csma/model/csma-channel.cc b/src/csma/model/csma-channel.cc +index 9c9f253a6..e09138e45 100644 +--- a/src/csma/model/csma-channel.cc ++++ b/src/csma/model/csma-channel.cc +@@ -1,5 +1,8 @@ + /* + * Copyright (c) 2007 Emmanuelle Laprise ++ * Copyright (c) 2012 Jeff Young ++ * Copyright (c) 2014 Murphy McCauley ++ * Copyright (c) 2017 Luciano Jerez Chaves + * + * 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 +@@ -15,6 +18,9 @@ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise ++ * Author: Jeff Young ++ * Author: Murphy McCauley ++ * Author: Luciano Jerez Chaves + */ + + #include "csma-channel.h" +@@ -50,7 +56,13 @@ CsmaChannel::GetTypeId() + "Transmission delay through the channel", + TimeValue(Seconds(0)), + MakeTimeAccessor(&CsmaChannel::m_delay), +- MakeTimeChecker()); ++ MakeTimeChecker()) ++ .AddAttribute("FullDuplex", ++ "Whether the channel is full-duplex mode.", ++ TypeId::ATTR_CONSTRUCT, ++ BooleanValue(false), ++ MakeBooleanAccessor(&CsmaChannel::m_fullDuplex), ++ MakeBooleanChecker()); + return tid; + } + +@@ -58,7 +70,6 @@ CsmaChannel::CsmaChannel() + : Channel() + { + NS_LOG_FUNCTION_NOARGS(); +- m_state = IDLE; + m_deviceList.clear(); + } + +@@ -74,9 +85,21 @@ CsmaChannel::Attach(Ptr device) + NS_LOG_FUNCTION(this << device); + NS_ASSERT(device); + ++ // ++ // For full-duplex links we can only attach two devices to the same channel ++ // since there is no backoff mechanism for concurrent transmissions. ++ // ++ if (m_fullDuplex && m_deviceList.size() >= 2) ++ { ++ NS_LOG_DEBUG("Falling back to half-duplex"); ++ m_fullDuplex = false; ++ } ++ + CsmaDeviceRec rec(device); + + m_deviceList.push_back(rec); ++ SetState(m_deviceList.size() - 1, IDLE); ++ SetCurrentSrc(m_deviceList.size() - 1, m_deviceList.size() - 1); + return (m_deviceList.size() - 1); + } + +@@ -110,7 +133,7 @@ CsmaChannel::Reattach(uint32_t deviceId) + { + NS_LOG_FUNCTION(this << deviceId); + +- if (deviceId < m_deviceList.size()) ++ if (deviceId >= m_deviceList.size()) + { + return false; + } +@@ -141,7 +164,7 @@ CsmaChannel::Detach(uint32_t deviceId) + + m_deviceList[deviceId].active = false; + +- if ((m_state == TRANSMITTING) && (m_currentSrc == deviceId)) ++ if ((GetState(deviceId) == TRANSMITTING) && (GetCurrentSrc(deviceId) == deviceId)) + { + NS_LOG_WARN("CsmaChannel::Detach(): Device is currently" + << "transmitting (" << deviceId << ")"); +@@ -179,7 +202,7 @@ CsmaChannel::TransmitStart(Ptr p, uint32_t srcId) + NS_LOG_FUNCTION(this << p << srcId); + NS_LOG_INFO("UID is " << p->GetUid() << ")"); + +- if (m_state != IDLE) ++ if (GetState(srcId) != IDLE) + { + NS_LOG_WARN("CsmaChannel::TransmitStart(): State is not IDLE"); + return false; +@@ -188,14 +211,14 @@ CsmaChannel::TransmitStart(Ptr p, uint32_t srcId) + if (!IsActive(srcId)) + { + NS_LOG_ERROR( +- "CsmaChannel::TransmitStart(): Seclected source is not currently attached to network"); ++ "CsmaChannel::TransmitStart(): Selected source is not currently attached to network"); + return false; + } + + NS_LOG_LOGIC("switch to TRANSMITTING"); +- m_currentPkt = p->Copy(); +- m_currentSrc = srcId; +- m_state = TRANSMITTING; ++ SetCurrentPkt(srcId, p->Copy()); ++ SetCurrentSrc(srcId, srcId); ++ SetState(srcId, TRANSMITTING); + return true; + } + +@@ -206,17 +229,23 @@ CsmaChannel::IsActive(uint32_t deviceId) + } + + bool +-CsmaChannel::TransmitEnd() ++CsmaChannel::IsFullDuplex() const ++{ ++ return m_fullDuplex; ++} ++ ++bool ++CsmaChannel::TransmitEnd(uint32_t srcId) + { +- NS_LOG_FUNCTION(this << m_currentPkt << m_currentSrc); +- NS_LOG_INFO("UID is " << m_currentPkt->GetUid() << ")"); ++ NS_LOG_FUNCTION(this << GetCurrentPkt(srcId) << GetCurrentSrc(srcId)); ++ NS_LOG_INFO("UID is " << GetCurrentPkt(srcId)->GetUid() << ")"); + +- NS_ASSERT(m_state == TRANSMITTING); +- m_state = PROPAGATING; ++ NS_ASSERT(GetState(srcId) == TRANSMITTING); ++ SetState(srcId, PROPAGATING); + + bool retVal = true; + +- if (!IsActive(m_currentSrc)) ++ if (!IsActive(GetCurrentSrc(srcId))) + { + NS_LOG_ERROR("CsmaChannel::TransmitEnd(): Seclected source was detached before the end of " + "the transmission"); +@@ -230,31 +259,47 @@ CsmaChannel::TransmitEnd() + std::vector::iterator it; + for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) + { +- if (it->IsActive() && it->devicePtr != m_deviceList[m_currentSrc].devicePtr) ++ if (it->IsActive() && it->devicePtr != m_deviceList[GetCurrentSrc(srcId)].devicePtr) + { + // schedule reception events + Simulator::ScheduleWithContext(it->devicePtr->GetNode()->GetId(), + m_delay, + &CsmaNetDevice::Receive, + it->devicePtr, +- m_currentPkt->Copy(), +- m_deviceList[m_currentSrc].devicePtr); ++ GetCurrentPkt(srcId)->Copy(), ++ m_deviceList[GetCurrentSrc(srcId)].devicePtr); + } + } + +- // also schedule for the tx side to go back to IDLE +- Simulator::Schedule(m_delay, &CsmaChannel::PropagationCompleteEvent, this); ++ // Schedule for the TX side to go back to IDLE. ++ if (IsFullDuplex()) ++ { ++ // ++ // In full-duplex mode, the channel should be IDLE during propagation ++ // since it's ok to start transmitting again. In this case, we don't need ++ // to wait for the channel delay. ++ // ++ PropagationCompleteEvent(srcId); ++ } ++ else ++ { ++ // ++ // In half-duplex mode, the channel can only go back to IDLE after ++ // propagation delay. ++ // ++ Simulator::Schedule(m_delay, &CsmaChannel::PropagationCompleteEvent, this, srcId); ++ } + return retVal; + } + + void +-CsmaChannel::PropagationCompleteEvent() ++CsmaChannel::PropagationCompleteEvent(uint32_t deviceId) + { +- NS_LOG_FUNCTION(this << m_currentPkt); +- NS_LOG_INFO("UID is " << m_currentPkt->GetUid() << ")"); ++ NS_LOG_FUNCTION(this << GetCurrentPkt(deviceId)); ++ NS_LOG_INFO("UID is " << GetCurrentPkt(deviceId)->GetUid() << ")"); + +- NS_ASSERT(m_state == PROPAGATING); +- m_state = IDLE; ++ NS_ASSERT(GetState(deviceId) == PROPAGATING); ++ SetState(deviceId, IDLE); + } + + uint32_t +@@ -308,9 +353,9 @@ CsmaChannel::GetDeviceNum(Ptr device) + } + + bool +-CsmaChannel::IsBusy() ++CsmaChannel::IsBusy(uint32_t deviceId) + { +- return m_state != IDLE; ++ return GetState(deviceId) != IDLE; + } + + DataRate +@@ -326,9 +371,9 @@ CsmaChannel::GetDelay() + } + + WireState +-CsmaChannel::GetState() ++CsmaChannel::GetState(uint32_t deviceId) + { +- return m_state; ++ return m_state[m_fullDuplex ? deviceId : 0]; + } + + Ptr +@@ -337,6 +382,36 @@ CsmaChannel::GetDevice(std::size_t i) const + return GetCsmaDevice(i); + } + ++Ptr ++CsmaChannel::GetCurrentPkt(uint32_t deviceId) ++{ ++ return m_currentPkt[m_fullDuplex ? deviceId : 0]; ++} ++ ++void ++CsmaChannel::SetCurrentPkt(uint32_t deviceId, Ptr pkt) ++{ ++ m_currentPkt[m_fullDuplex ? deviceId : 0] = pkt; ++} ++ ++uint32_t ++CsmaChannel::GetCurrentSrc(uint32_t deviceId) ++{ ++ return m_currentSrc[m_fullDuplex ? deviceId : 0]; ++} ++ ++void ++CsmaChannel::SetCurrentSrc(uint32_t deviceId, uint32_t transmitterId) ++{ ++ m_currentSrc[m_fullDuplex ? deviceId : 0] = transmitterId; ++} ++ ++void ++CsmaChannel::SetState(uint32_t deviceId, WireState state) ++{ ++ m_state[m_fullDuplex ? deviceId : 0] = state; ++} ++ + CsmaDeviceRec::CsmaDeviceRec() + { + active = false; +diff --git a/src/csma/model/csma-channel.h b/src/csma/model/csma-channel.h +index da4e948da..5d824f073 100644 +--- a/src/csma/model/csma-channel.h ++++ b/src/csma/model/csma-channel.h +@@ -1,5 +1,8 @@ + /* + * Copyright (c) 2007 Emmanuelle Laprise ++ * Copyright (c) 2012 Jeffrey Young ++ * Copyright (c) 2014 Murphy McCauley ++ * Copyright (c) 2017 Luciano Jerez Chaves + * + * 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 +@@ -15,11 +18,15 @@ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise ++ * Author: Jeff Young ++ * Author: Murphy McCauley ++ * Author: Luciano Jerez Chaves + */ + + #ifndef CSMA_CHANNEL_H + #define CSMA_CHANNEL_H + ++#include "ns3/boolean.h" + #include "ns3/channel.h" + #include "ns3/data-rate.h" + #include "ns3/nstime.h" +@@ -86,7 +93,11 @@ enum WireState + * when many nodes are connected to one wire. It uses a single busy + * flag to indicate if the channel is currently in use. It does not + * take into account the distances between stations or the speed of +- * light to determine collisions. ++ * light to determine collisions. Optionally, it allows for full- ++ * duplex operation when there are only two attached nodes. To ++ * implement full-duplex, we internally keep two TX "subchannels" ++ * (one for each attached node). When in half-duplex mode, only ++ * the first subchannel is used. + */ + class CsmaChannel : public Channel + { +@@ -201,19 +212,23 @@ class CsmaChannel : public Channel + * packet p as the m_currentPkt, the packet being currently + * transmitting. + * ++ * \param deviceId The ID that was assigned to the net device when ++ * it was attached to the channel. + * \return Returns true unless the source was detached before it + * completed its transmission. + */ +- bool TransmitEnd(); ++ bool TransmitEnd(uint32_t deviceId); + + /** + * \brief Indicates that the channel has finished propagating the + * current packet. The channel is released and becomes free. + * +- * Calls the receive function of every active net device that is ++ * \param deviceId The ID that was assigned to the net device when ++ * it was attached to the channel. ++ * Calls the receive function of the other net device that is + * attached to the channel. + */ +- void PropagationCompleteEvent(); ++ void PropagationCompleteEvent(uint32_t deviceId); + + /** + * \return Returns the device number assigned to a net device by the +@@ -225,19 +240,25 @@ class CsmaChannel : public Channel + int32_t GetDeviceNum(Ptr device); + + /** ++ * \brief Checks the state of the channel. ++ * ++ * \param deviceId The ID that was assigned to the net device when ++ * it was attached to the channel. + * \return Returns the state of the channel (IDLE -- free, + * TRANSMITTING -- busy, PROPAGATING - busy ) + */ +- WireState GetState(); ++ WireState GetState(uint32_t deviceId); + + /** + * \brief Indicates if the channel is busy. The channel will only + * accept new packets for transmission if it is not busy. + * ++ * \param deviceId The ID that was assigned to the net device when ++ * it was attached to the channel. + * \return Returns true if the channel is busy and false if it is + * free. + */ +- bool IsBusy(); ++ bool IsBusy(uint32_t deviceId); + + /** + * \brief Indicates if a net device is currently attached or +@@ -250,6 +271,14 @@ class CsmaChannel : public Channel + */ + bool IsActive(uint32_t deviceId); + ++ /** ++ * \brief Indicates if channel is operating in full-duplex mode. ++ * ++ * \return Returns true if channel is in full-duplex mode, false if in ++ * half-duplex mode. ++ */ ++ bool IsFullDuplex() const; ++ + /** + * \return Returns the number of net devices that are currently + * attached to the channel. +@@ -307,6 +336,11 @@ class CsmaChannel : public Channel + */ + Time m_delay; + ++ /** ++ * Whether the channel is in full-duplex mode. ++ */ ++ bool m_fullDuplex; ++ + /** + * List of the net devices that have been or are currently connected + * to the channel. +@@ -321,23 +355,75 @@ class CsmaChannel : public Channel + std::vector m_deviceList; + + /** +- * The Packet that is currently being transmitted on the channel (or last +- * packet to have been transmitted on the channel if the channel is +- * free.) ++ * The Packet that is currently being transmitted on the subchannel (or the ++ * last packet to have been transmitted if the subchannel is free). ++ * In half-duplex mode, only the first subchannel is used. + */ +- Ptr m_currentPkt; ++ Ptr m_currentPkt[2]; + + /** + * Device Id of the source that is currently transmitting on the ++ * subchannel, or the last source to have transmitted a packet on the ++ * subchannel, if it is not currently busy. ++ * In half-duplex mode, only the first subchannel is used. ++ */ ++ uint32_t m_currentSrc[2]; ++ ++ /** ++ * Current state of each subchannel. ++ * In half-duplex mode, only the first subchannel is used. ++ */ ++ WireState m_state[2]; ++ ++ /** ++ * \brief Gets current packet ++ * ++ * \param deviceId The ID that was assigned to the net device when ++ * it was attached to the channel. ++ * \return Device Id of the source that is currently transmitting on the ++ * subchannel or the last source to have transmitted a packet on the ++ * subchannel, if it is not currently busy. ++ */ ++ Ptr GetCurrentPkt(uint32_t deviceId); ++ ++ /** ++ * \brief Sets the current packet ++ * ++ * \param deviceId The ID that was assigned to the net device when ++ * it was attached to the channel. ++ * \param The Packet that is current being transmitted by deviceId (or last ++ * packet to have been transmitted on the channel if the channel is free.) ++ */ ++ void SetCurrentPkt(uint32_t deviceId, Ptr pkt); ++ ++ /** ++ * \brief Gets current transmitter ++ * ++ * \param deviceId The ID that was assigned to the net device when ++ * it was attached to the channel. ++ * \return Device Id of the source that is currently transmitting on the + * channel. Or last source to have transmitted a packet on the + * channel, if the channel is currently not busy. + */ +- uint32_t m_currentSrc; ++ uint32_t GetCurrentSrc(uint32_t deviceId); + + /** +- * Current state of the channel ++ * \brief Sets the current transmitter ++ * ++ * \param deviceId The ID that was assigned to the net device when ++ * it was attached to the channel. ++ * \param transmitterId The ID of the transmitting device. ++ */ ++ void SetCurrentSrc(uint32_t deviceId, uint32_t transmitterId); ++ ++ /** ++ * \brief Sets the state of the channel ++ * ++ * \param deviceId The ID that was assigned to the net device when ++ * it was attached to the channel. ++ * \param state The new channel state. + */ +- WireState m_state; ++ void SetState(uint32_t deviceId, WireState state); + }; + + } // namespace ns3 +diff --git a/src/csma/model/csma-net-device.cc b/src/csma/model/csma-net-device.cc +index f6d3ff4ae..e2998cd19 100644 +--- a/src/csma/model/csma-net-device.cc ++++ b/src/csma/model/csma-net-device.cc +@@ -1,5 +1,8 @@ + /* + * Copyright (c) 2007 Emmanuelle Laprise ++ * Copyright (c) 2012 Jeffrey Young ++ * Copyright (c) 2014 Murphy McCauley ++ * Copyright (c) 2017 Luciano Jerez Chaves + * + * 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 +@@ -15,6 +18,9 @@ + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Emmanuelle Laprise ++ * Author: Jeff Young ++ * Author: Murphy McCauley ++ * Author: Luciano Jerez Chaves + */ + + #include "csma-net-device.h" +@@ -455,6 +461,7 @@ CsmaNetDevice::TransmitStart() + + NS_LOG_LOGIC("m_currentPkt = " << m_currentPkt); + NS_LOG_LOGIC("UID = " << m_currentPkt->GetUid()); ++ NS_LOG_LOGIC("Device ID = " << m_deviceId); + + // + // Only transmit if the send side of net device is enabled +@@ -476,34 +483,38 @@ CsmaNetDevice::TransmitStart() + "Must be READY to transmit. Tx state is: " << m_txMachineState); + + // +- // Now we have to sense the state of the medium and either start transmitting +- // if it is idle, or backoff our transmission if someone else is on the wire. ++ // Now we sense the state of the medium. If idle, we start transmitting. ++ // Otherwise, we have to wait. + // +- if (m_channel->GetState() != IDLE) ++ if (m_channel->GetState(m_deviceId) != IDLE) + { + // +- // The channel is busy -- backoff and rechedule TransmitStart() unless +- // we have exhausted all of our retries. ++ // The (sub)channel is busy. If in half-duplex mode, backoff and ++ // reschedule TransmitStart() unless we have exhausted all of our ++ // retries. This is not supposed to happen in full-duplex mode. + // +- m_txMachineState = BACKOFF; +- +- if (m_backoff.MaxRetriesReached()) +- { +- // +- // Too many retries, abort transmission of packet +- // +- TransmitAbort(); +- } +- else ++ if (m_channel->IsFullDuplex() == false) + { +- m_macTxBackoffTrace(m_currentPkt); +- +- m_backoff.IncrNumRetries(); +- Time backoffTime = m_backoff.GetBackoffTime(); +- +- NS_LOG_LOGIC("Channel busy, backing off for " << backoffTime.As(Time::S)); +- +- Simulator::Schedule(backoffTime, &CsmaNetDevice::TransmitStart, this); ++ m_txMachineState = BACKOFF; ++ ++ if (m_backoff.MaxRetriesReached()) ++ { ++ // ++ // Too many retries, abort transmission of packet ++ // ++ TransmitAbort(); ++ } ++ else ++ { ++ m_macTxBackoffTrace(m_currentPkt); ++ ++ m_backoff.IncrNumRetries(); ++ Time backoffTime = m_backoff.GetBackoffTime(); ++ ++ NS_LOG_LOGIC("Channel busy, backing off for " << backoffTime.As(Time::S)); ++ ++ Simulator::Schedule(backoffTime, &CsmaNetDevice::TransmitStart, this); ++ } + } + } + else +@@ -595,7 +606,7 @@ CsmaNetDevice::TransmitCompleteEvent() + // + NS_ASSERT_MSG(m_txMachineState == BUSY, + "CsmaNetDevice::transmitCompleteEvent(): Must be BUSY if transmitting"); +- NS_ASSERT(m_channel->GetState() == TRANSMITTING); ++ NS_ASSERT(m_channel->GetState(m_deviceId) == TRANSMITTING); + m_txMachineState = GAP; + + // +@@ -605,8 +616,9 @@ CsmaNetDevice::TransmitCompleteEvent() + NS_ASSERT_MSG(m_currentPkt, "CsmaNetDevice::TransmitCompleteEvent(): m_currentPkt zero"); + NS_LOG_LOGIC("m_currentPkt=" << m_currentPkt); + NS_LOG_LOGIC("Pkt UID is " << m_currentPkt->GetUid() << ")"); ++ NS_LOG_LOGIC("Device ID is " << m_deviceId); + +- m_channel->TransmitEnd(); ++ m_channel->TransmitEnd(m_deviceId); + m_phyTxEndTrace(m_currentPkt); + m_currentPkt = nullptr; + +@@ -663,6 +675,8 @@ CsmaNetDevice::Attach(Ptr ch) + + m_deviceId = m_channel->Attach(this); + ++ NS_LOG_FUNCTION("Device ID is " << m_deviceId); ++ + // + // The channel provides us with the transmitter data rate. + // +@@ -699,6 +713,7 @@ CsmaNetDevice::Receive(Ptr packet, Ptr senderDevice) + { + NS_LOG_FUNCTION(packet << senderDevice); + NS_LOG_LOGIC("UID is " << packet->GetUid()); ++ NS_LOG_LOGIC("Device ID is " << m_deviceId); + + // + // We never forward up packets that we sent. Real devices don't do this since +@@ -996,6 +1011,7 @@ CsmaNetDevice::SendFrom(Ptr packet, + NS_LOG_FUNCTION(packet << src << dest << protocolNumber); + NS_LOG_LOGIC("packet =" << packet); + NS_LOG_LOGIC("UID is " << packet->GetUid() << ")"); ++ NS_LOG_LOGIC("Device ID is " << m_deviceId); + + NS_ASSERT(IsLinkUp()); + +@@ -1052,13 +1068,6 @@ CsmaNetDevice::GetNode() const + return m_node; + } + +-void +-CsmaNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) +-{ +- NS_LOG_FUNCTION(&cb); +- m_openFlowRxCallback = cb; +-} +- + void + CsmaNetDevice::SetNode(Ptr node) + { +@@ -1074,6 +1083,13 @@ CsmaNetDevice::NeedsArp() const + return true; + } + ++void ++CsmaNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) ++{ ++ NS_LOG_FUNCTION(&cb); ++ m_openFlowRxCallback = cb; ++} ++ + void + CsmaNetDevice::SetReceiveCallback(NetDevice::ReceiveCallback cb) + { +diff --git a/src/csma/test/examples-to-run.py b/src/csma/test/examples-to-run.py +index 3e49f1972..c671e5427 100644 +--- a/src/csma/test/examples-to-run.py ++++ b/src/csma/test/examples-to-run.py +@@ -8,6 +8,7 @@ + # See test.py for more information. + cpp_examples = [ + ("csma-broadcast", "True", "True"), ++ ("csma-duplex", "True", "True"), + ("csma-multicast", "True", "True"), + ("csma-one-subnet", "True", "True"), + ("csma-packet-socket", "True", "True"), +-- +2.34.1 + diff --git a/utils/ofswitch13-3_38.patch b/utils/ofswitch13-3_38.patch index 316f97a..0865000 100644 --- a/utils/ofswitch13-3_38.patch +++ b/utils/ofswitch13-3_38.patch @@ -1,3 +1,16 @@ +From 598058c4f0d47d8635b1b57d62068195cba7f006 Mon Sep 17 00:00:00 2001 +From: Luciano J Chaves +Date: Fri, 1 Sep 2023 10:03:56 -0300 +Subject: [PATCH] OFSwitch13 patch + +--- + .../custom-modules/ns3-configtable.cmake | 3 ++ + src/csma/model/csma-net-device.cc | 35 +++++++++++++++++++ + src/csma/model/csma-net-device.h | 13 +++++++ + .../model/virtual-net-device.cc | 30 ++++++++++++++++ + .../model/virtual-net-device.h | 11 ++++++ + 5 files changed, 92 insertions(+) + diff --git a/build-support/custom-modules/ns3-configtable.cmake b/build-support/custom-modules/ns3-configtable.cmake index c3baa514b..3b7434750 100644 --- a/build-support/custom-modules/ns3-configtable.cmake @@ -171,3 +184,6 @@ index 66718596a..c0eb0c468 100644 }; } // namespace ns3 +-- +2.34.1 + diff --git a/utils/ofswitch13-3_39.patch b/utils/ofswitch13-3_39.patch new file mode 100644 index 0000000..7f72cfc --- /dev/null +++ b/utils/ofswitch13-3_39.patch @@ -0,0 +1,189 @@ +From b89fa2043c3af1edd2270eb375756d6525bff331 Mon Sep 17 00:00:00 2001 +From: Luciano J Chaves +Date: Fri, 1 Sep 2023 09:53:24 -0300 +Subject: [PATCH] OFSwitch13 patch + +--- + .../custom-modules/ns3-configtable.cmake | 3 ++ + src/csma/model/csma-net-device.cc | 35 +++++++++++++++++++ + src/csma/model/csma-net-device.h | 13 +++++++ + .../model/virtual-net-device.cc | 30 ++++++++++++++++ + .../model/virtual-net-device.h | 11 ++++++ + 5 files changed, 92 insertions(+) + +diff --git a/build-support/custom-modules/ns3-configtable.cmake b/build-support/custom-modules/ns3-configtable.cmake +index c3baa514b..3b7434750 100644 +--- a/build-support/custom-modules/ns3-configtable.cmake ++++ b/build-support/custom-modules/ns3-configtable.cmake +@@ -161,6 +161,9 @@ macro(write_configtable) + string(APPEND out "ns-3 Click Integration : ") + check_on_or_off("ON" "${NS3_CLICK}") + ++ string(APPEND out "ns-3 OFSwitch13 Integration : ") ++ check_on_or_off("ON" "${NS3_OFSWITCH13}") ++ + string(APPEND out "ns-3 OpenFlow Integration : ") + check_on_or_off("ON" "${NS3_OPENFLOW}") + +diff --git a/src/csma/model/csma-net-device.cc b/src/csma/model/csma-net-device.cc +index bb0b93894..f6d3ff4ae 100644 +--- a/src/csma/model/csma-net-device.cc ++++ b/src/csma/model/csma-net-device.cc +@@ -806,6 +806,34 @@ CsmaNetDevice::Receive(Ptr packet, Ptr senderDevice) + packetType = PACKET_OTHERHOST; + } + ++ // ++ // Check if this device is configure as an OpenFlow switch port. ++ // ++ if (!m_openFlowRxCallback.IsNull()) ++ { ++ // For all kinds of packet we receive, we hit the promiscuous sniffer ++ // hook. If the packet is addressed to this device (which is not supposed ++ // to happen in normal situations), we also hit the non-promiscuous ++ // sniffer hook, but in both cases we don't forward the packet up the ++ // stack. ++ m_promiscSnifferTrace(originalPacket); ++ if (packetType != PACKET_OTHERHOST) ++ { ++ m_snifferTrace(originalPacket); ++ } ++ ++ // We forward the original packet (which includes the EthernetHeader) to ++ // the OpenFlow receive callback for all kinds of packetType we receive ++ // (broadcast, multicast, host or other host). ++ m_openFlowRxCallback(this, ++ originalPacket, ++ protocol, ++ header.GetSource(), ++ header.GetDestination(), ++ packetType); ++ return; ++ } ++ + // + // For all kinds of packetType we receive, we hit the promiscuous sniffer + // hook and pass a copy up to the promiscuous callback. Pass a copy to +@@ -1024,6 +1052,13 @@ CsmaNetDevice::GetNode() const + return m_node; + } + ++void ++CsmaNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) ++{ ++ NS_LOG_FUNCTION(&cb); ++ m_openFlowRxCallback = cb; ++} ++ + void + CsmaNetDevice::SetNode(Ptr node) + { +diff --git a/src/csma/model/csma-net-device.h b/src/csma/model/csma-net-device.h +index 237daf37e..226ea7477 100644 +--- a/src/csma/model/csma-net-device.h ++++ b/src/csma/model/csma-net-device.h +@@ -312,6 +312,14 @@ class CsmaNetDevice : public NetDevice + */ + bool NeedsArp() const override; + ++ /** ++ * Set the callback used to notify the OpenFlow when a packet has been ++ * received by this device. ++ * ++ * \param cb The callback. ++ */ ++ void SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb); ++ + /** + * Set the callback to be used to notify higher layers when a packet has been + * received. +@@ -692,6 +700,11 @@ class CsmaNetDevice : public NetDevice + */ + Mac48Address m_address; + ++ /** ++ * The OpenFlow receive callback. ++ */ ++ NetDevice::PromiscReceiveCallback m_openFlowRxCallback; ++ + /** + * The callback used to notify higher layers that a packet has been received. + */ +diff --git a/src/virtual-net-device/model/virtual-net-device.cc b/src/virtual-net-device/model/virtual-net-device.cc +index 31518b7dc..e7613508f 100644 +--- a/src/virtual-net-device/model/virtual-net-device.cc ++++ b/src/virtual-net-device/model/virtual-net-device.cc +@@ -142,6 +142,29 @@ VirtualNetDevice::Receive(Ptr packet, + const Address& destination, + PacketType packetType) + { ++ // ++ // Check if this device is configure as an OpenFlow switch port. ++ // ++ if (!m_openFlowRxCallback.IsNull()) ++ { ++ // For all kinds of packetType we receive, we hit the promiscuous sniffer ++ // hook. If the packet is addressed to this device (which is not supposed ++ // to happen in normal situations), we also hit the non-promiscuous ++ // sniffer hook, but in both cases we don't forward the packet up the ++ // stack. ++ m_promiscSnifferTrace(packet); ++ if (packetType != PACKET_OTHERHOST) ++ { ++ m_snifferTrace(packet); ++ } ++ ++ // We then forward the original packet to the OpenFlow receive callback ++ // for all kinds of packetType we receive (broadcast, multicast, host or ++ // other host). ++ m_openFlowRxCallback(this, packet, protocol, source, destination, packetType); ++ return true; ++ } ++ + // + // For all kinds of packetType we receive, we hit the promiscuous sniffer + // hook and pass a copy up to the promiscuous callback. Pass a copy to +@@ -311,4 +334,11 @@ VirtualNetDevice::IsBridge() const + return false; + } + ++void ++VirtualNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) ++{ ++ NS_LOG_FUNCTION(&cb); ++ m_openFlowRxCallback = cb; ++} ++ + } // namespace ns3 +diff --git a/src/virtual-net-device/model/virtual-net-device.h b/src/virtual-net-device/model/virtual-net-device.h +index 66718596a..c0eb0c468 100644 +--- a/src/virtual-net-device/model/virtual-net-device.h ++++ b/src/virtual-net-device/model/virtual-net-device.h +@@ -153,6 +153,14 @@ class VirtualNetDevice : public NetDevice + bool SupportsSendFrom() const override; + bool IsBridge() const override; + ++ /** ++ * Set the callback used to notify the OpenFlow when a packet has been ++ * received by this device. ++ * ++ * \param cb The OpenFlow receive callback. ++ */ ++ void SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb); ++ + protected: + void DoDispose() override; + +@@ -173,6 +181,9 @@ class VirtualNetDevice : public NetDevice + bool m_needsArp; //!< True if the device needs ARP + bool m_supportsSendFrom; //!< True if the device supports SendFrm + bool m_isPointToPoint; //!< True if the device is a PointToPoint type device ++ ++ /** The OpenFlow receive callback. */ ++ NetDevice::PromiscReceiveCallback m_openFlowRxCallback; + }; + + } // namespace ns3 +-- +2.34.1 +