├── .editorconfig ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── RELEASE_NOTES.md ├── doc ├── Makefile └── source │ ├── conf.py │ ├── figures │ ├── ofswitch13-controller.pdf │ ├── ofswitch13-module.pdf │ ├── ofswitch13-qos-topology.pdf │ └── ofswitch13-switch.pdf │ ├── ofswitch13-description.rst │ ├── ofswitch13-usage.rst │ └── ofswitch13.rst ├── examples ├── CMakeLists.txt ├── ofswitch13-custom-switch.cc ├── ofswitch13-external-controller.cc ├── ofswitch13-first.cc ├── ofswitch13-logical-port │ ├── gtp-tunnel-app.cc │ ├── gtp-tunnel-app.h │ ├── main.cc │ ├── tunnel-controller.cc │ └── tunnel-controller.h ├── ofswitch13-multiple-controllers.cc ├── ofswitch13-multiple-domains.cc ├── ofswitch13-qos-controller │ ├── main.cc │ ├── qos-controller.cc │ └── qos-controller.h └── ofswitch13-single-domain.cc ├── helper ├── ofswitch13-device-container.cc ├── ofswitch13-device-container.h ├── ofswitch13-external-helper.cc ├── ofswitch13-external-helper.h ├── ofswitch13-helper.cc ├── ofswitch13-helper.h ├── ofswitch13-internal-helper.cc ├── ofswitch13-internal-helper.h ├── ofswitch13-stats-calculator.cc └── ofswitch13-stats-calculator.h ├── model ├── ofswitch13-controller.cc ├── ofswitch13-controller.h ├── ofswitch13-device.cc ├── ofswitch13-device.h ├── ofswitch13-interface.cc ├── ofswitch13-interface.h ├── ofswitch13-learning-controller.cc ├── ofswitch13-learning-controller.h ├── ofswitch13-port.cc ├── ofswitch13-port.h ├── ofswitch13-priority-queue.cc ├── ofswitch13-priority-queue.h ├── ofswitch13-queue.cc ├── ofswitch13-queue.h ├── ofswitch13-socket-handler.cc ├── ofswitch13-socket-handler.h ├── queue-tag.cc ├── queue-tag.h ├── tunnel-id-tag.cc └── tunnel-id-tag.h └── utils ├── csma-full-duplex-3_38.patch ├── csma-full-duplex-3_39.patch ├── csma-full-duplex-3_40.patch ├── ofswitch13-3_38.patch ├── ofswitch13-3_39.patch └── ofswitch13-3_40.patch /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = false 5 | 6 | [*.md] 7 | trim_trailing_whitespace = false 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | doc/build 2 | doc/source/figures/*.png 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(NS3_OFSWITCH13 2 | "OFF" 3 | CACHE INTERNAL 4 | "ON if OFSwitch13 is found." 5 | ) 6 | 7 | # Check for BOOST dependency 8 | check_include_files( 9 | "boost/static_assert.hpp" 10 | BOOST_STATIC_ASSERT_FOUND 11 | LANGUAGE 12 | CXX 13 | ) 14 | 15 | if(NOT BOOST_STATIC_ASSERT_FOUND) 16 | message(${HIGHLIGHTED_STATUS} "BOOST static assert was not found.") 17 | message(${HIGHLIGHTED_STATUS} "Skipping OFSwitch13") 18 | return() 19 | endif() 20 | 21 | # Check for BOFUSS dependency 22 | 23 | # List of BOFUSS headers files required by OFSwitch13 24 | set(NS3_OFSWITCH13_BOFUSS_HEADERS 25 | bofuss/action_set.h 26 | bofuss/datapath.h 27 | bofuss/dp_actions.h 28 | bofuss/dp_buffers.h 29 | bofuss/dp_control.h 30 | bofuss/dp_ports.h 31 | bofuss/dpctl.h 32 | bofuss/flow_entry.h 33 | bofuss/flow_table.h 34 | bofuss/group_entry.h 35 | bofuss/group_table.h 36 | bofuss/match_std.h 37 | bofuss/meter_entry.h 38 | bofuss/meter_table.h 39 | bofuss/ofl-actions.h 40 | bofuss/ofl-err.h 41 | bofuss/ofl-messages.h 42 | bofuss/ofl-print.h 43 | bofuss/ofl-structs.h 44 | bofuss/ofpbuf.h 45 | bofuss/openflow.h 46 | bofuss/oxm-match.h 47 | bofuss/packet_handle_std.h 48 | bofuss/packet.h 49 | bofuss/pipeline.h 50 | bofuss/timeval.h 51 | bofuss/vlog.h 52 | ) 53 | 54 | set(NS3_OFSWITCH13_BOFUSS_PATH 55 | "" 56 | CACHE PATH 57 | "The BOFUSS library path" 58 | ) 59 | message(STATUS "Looking for BOFUSS library in ${NS3_OFSWITCH13_BOFUSS_PATH}") 60 | 61 | find_external_library( 62 | DEPENDENCY_NAME bofuss 63 | LIBRARY_NAME bofuss 64 | HEADER_NAMES ${NS3_OFSWITCH13_BOFUSS_HEADERS} 65 | SEARCH_PATHS ${NS3_OFSWITCH13_BOFUSS_PATH} 66 | ) 67 | 68 | if(NOT bofuss_FOUND AND NOT ${bofuss_FOUND}) 69 | message(${HIGHLIGHTED_STATUS} "BOFUSS library was not found.") 70 | message(${HIGHLIGHTED_STATUS} "The build system will try to download and compile it!") 71 | 72 | include(ExternalProject) 73 | ExternalProject_Add( 74 | bofuss_dep 75 | GIT_REPOSITORY https://github.com/ljerezchaves/ofsoftswitch13.git 76 | GIT_TAG 1b6106e3e3814c50b323e43b6bb2dec5ab13ffe7 77 | PREFIX bofuss_dep 78 | BUILD_IN_SOURCE TRUE 79 | UPDATE_DISCONNECTED TRUE 80 | CONFIGURE_COMMAND ./configure --prefix ${CMAKE_OUTPUT_DIRECTORY} 81 | BUILD_COMMAND make -j${NumThreads} 82 | INSTALL_COMMAND make install 83 | LOG_DOWNLOAD true 84 | LOG_UPDATE true 85 | LOG_CONFIGURE true 86 | LOG_BUILD true 87 | LOG_INSTALL true 88 | LOG_OUTPUT_ON_FAILURE true 89 | ) 90 | 91 | set(bofuss_LIBRARIES bofuss) 92 | endif() 93 | 94 | # Enabling OFSwitch13 compilation 95 | set(NS3_OFSWITCH13 96 | "ON" 97 | CACHE INTERNAL 98 | "ON if OFSwitch13 is found." 99 | ) 100 | 101 | include_directories(${bofuss_INCLUDE_DIRS}) 102 | add_definitions(-DNS3_OFSWITCH13) 103 | 104 | # OFSwitch13 source files 105 | set(source_files 106 | model/ofswitch13-controller.cc 107 | model/ofswitch13-device.cc 108 | model/ofswitch13-interface.cc 109 | model/ofswitch13-learning-controller.cc 110 | model/ofswitch13-queue.cc 111 | model/ofswitch13-priority-queue.cc 112 | model/ofswitch13-port.cc 113 | model/ofswitch13-socket-handler.cc 114 | model/queue-tag.cc 115 | model/tunnel-id-tag.cc 116 | helper/ofswitch13-device-container.cc 117 | helper/ofswitch13-external-helper.cc 118 | helper/ofswitch13-helper.cc 119 | helper/ofswitch13-internal-helper.cc 120 | helper/ofswitch13-stats-calculator.cc 121 | ) 122 | 123 | # OFSwitch13 header files 124 | set(header_files 125 | model/ofswitch13-controller.h 126 | model/ofswitch13-device.h 127 | model/ofswitch13-interface.h 128 | model/ofswitch13-learning-controller.h 129 | model/ofswitch13-queue.h 130 | model/ofswitch13-priority-queue.h 131 | model/ofswitch13-port.h 132 | model/ofswitch13-socket-handler.h 133 | model/queue-tag.h 134 | model/tunnel-id-tag.h 135 | helper/ofswitch13-device-container.h 136 | helper/ofswitch13-external-helper.h 137 | helper/ofswitch13-helper.h 138 | helper/ofswitch13-internal-helper.h 139 | helper/ofswitch13-stats-calculator.h 140 | ) 141 | 142 | # OFSwitch13 test files 143 | set(test_sources 144 | ) 145 | 146 | # Libraries to link to the OFSwitch13 module 147 | set(libraries_to_link 148 | ${libcore} 149 | ${libnetwork} 150 | ${libinternet} 151 | ${libcsma} 152 | ${libpoint-to-point} 153 | ${libvirtual-net-device} 154 | ${bofuss_LIBRARIES} 155 | ) 156 | 157 | # Build the OFSwitch13 module 158 | build_lib( 159 | LIBNAME ofswitch13 160 | SOURCE_FILES ${source_files} 161 | HEADER_FILES ${header_files} 162 | LIBRARIES_TO_LINK ${libraries_to_link} 163 | TEST_SOURCES ${test_sources} 164 | ) 165 | 166 | # Add BOFUSS dependency to OFSwitch13 module 167 | if(NOT bofuss_FOUND AND NOT ${bofuss_FOUND}) 168 | add_dependencies(${libofswitch13} bofuss_dep) 169 | if(NOT ${XCODE}) 170 | add_dependencies(${libofswitch13}-obj bofuss_dep) 171 | endif() 172 | endif() 173 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenFlow 1.3 module for ns-3 2 | 3 | The OFSwitch13 module enhances the [ns-3 Network Simulator][ns-3] with Software-Defined Networking (SDN) capabilities. 4 | OFSwitch13 supports [OpenFlow protocol version 1.3][ofp13], bringing a switch device and a controller application interface to the ns-3 simulator. 5 | With OFSwitch13, it is possible to interconnect ns-3 nodes to send and receive traffic using the existing CSMA and virtual network devices. 6 | Extending the controller application interface allows users to implement any desired control logic to orchestrate the network. 7 | The communication between the controller and the switches happens over standard ns-3 protocol stack, devices, and channels. 8 | The OFSwitch13 module relies on the external [BOFUSS library][bofuss] that provides the switch datapath implementation and the support for OpenFlow messages in wire format. 9 | 10 | Please visit the [OFSwitch13 project homepage][project] and refer to the documentation for details about the module design, installation, and usage. 11 | 12 | ## License 13 | 14 | The OFSwitch13 module is a free software licensed under the [GNU GPLv2 license][gpl]. 15 | 16 | ## Contribute 17 | 18 | The OFSwitch13 module is currently maintained by Luciano Jerez Chaves. 19 | It also received contributions from Vítor Marge Eichemberger, Islene Calciolari Garcia, Arthur Boechat Mazzi, and Pasquale Imputato. 20 | We thank Eder Leão Fernandes for helping with the BOFUSS library integration. 21 | 22 | Please contribute to this project by submitting your bug reports to the [issue tracker][issues]. For fixes and improvements, consider creating a pull request. 23 | 24 | ## Contact 25 | 26 | Feel free to subscribe to the [mailing list at Google Groups][group] and provide feedback, give suggestions, interact with other users, or say hello! 27 | 28 | [ns-3]: https://www.nsnam.org 29 | [ofp13]: https://www.opennetworking.org/sdn-resources/technical-library 30 | [bofuss]: https://github.com/ljerezchaves/ofsoftswitch13 31 | [project]: http://www.lrc.ic.unicamp.br/ofswitch13/ 32 | [issues]: https://github.com/ljerezchaves/ofswitch13-module/issues 33 | [gpl]: http://www.gnu.org/copyleft/gpl.html 34 | [group]: https://groups.google.com/forum/#!forum/ofswitch13-users 35 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | SOURCE = source 2 | FIGURES = $(SOURCE)/figures 3 | 4 | # specify .pdf figures (from which .png will be generated) 5 | IMAGES_PDF = \ 6 | $(FIGURES)/ofswitch13-module.pdf \ 7 | $(FIGURES)/ofswitch13-switch.pdf \ 8 | $(FIGURES)/ofswitch13-controller.pdf \ 9 | $(FIGURES)/ofswitch13-qos-topology.pdf \ 10 | 11 | IMAGES_PNG = ${IMAGES_PDF:.pdf=.png} 12 | 13 | CONVERT = convert 14 | RESCALE = ../../../utils/rescale-pdf.sh 15 | 16 | # rescale pdf figures as necessary 17 | $(FIGURES)/ofswitch13-module.pdf_width = 12cm 18 | $(FIGURES)/ofswitch13-switch.pdf_width = 10cm 19 | $(FIGURES)/ofswitch13-controller.pdf_width = 10cm 20 | $(FIGURES)/ofswitch13-qos-topology.pdf_width = 12cm 21 | 22 | %.png : %.pdf 23 | @if test x$($<_width) != x; then $(RESCALE) $($<_width) $< ; fi 24 | @echo convert $(notdir $<) to $(notdir $@) 25 | @$(CONVERT) $< $@ >/dev/null 26 | 27 | # You can set these variables from the command line. 28 | SPHINXOPTS = 29 | SPHINXBUILD = sphinx-build 30 | PAPER = 31 | BUILDDIR = build 32 | 33 | # Internal variables. 34 | PAPEROPT_a4 = -D latex_paper_size=a4 35 | PAPEROPT_letter = -D latex_paper_size=letter 36 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCE) 37 | 38 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 39 | 40 | help: 41 | @echo "Please use \`make ' where is one of" 42 | @echo " html to make standalone HTML files" 43 | @echo " dirhtml to make HTML files named index.html in directories" 44 | @echo " singlehtml to make a single large HTML file" 45 | @echo " pickle to make pickle files" 46 | @echo " json to make JSON files" 47 | @echo " htmlhelp to make HTML files and a HTML help project" 48 | @echo " qthelp to make HTML files and a qthelp project" 49 | @echo " devhelp to make HTML files and a Devhelp project" 50 | @echo " epub to make an epub" 51 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 52 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 53 | @echo " text to make text files" 54 | @echo " man to make manual pages" 55 | @echo " changes to make an overview of all changed/added/deprecated items" 56 | @echo " linkcheck to check all external links for integrity" 57 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 58 | 59 | clean: 60 | -rm -rf $(BUILDDIR)/* 61 | -rm -f $(IMAGES_PNG) 62 | 63 | images: $(IMAGES_PNG) 64 | 65 | frag: pickle 66 | @if test ! -d $(BUILDDIR)/frag; then mkdir $(BUILDDIR)/frag; fi 67 | pushd $(BUILDDIR)/frag && ../../pickle-to-xml.py ../pickle/index.fpickle > navigation.xml && popd 68 | cp -r $(BUILDDIR)/pickle/_images $(BUILDDIR)/frag 69 | 70 | html: $(IMAGES_PNG) 71 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 72 | @echo 73 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 74 | 75 | dirhtml: $(IMAGES_PNG) 76 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 77 | @echo 78 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 79 | 80 | singlehtml: $(IMAGES_PNG) 81 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 82 | @echo 83 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 84 | 85 | pickle: $(IMAGES_PNG) 86 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 87 | @echo 88 | @echo "Build finished; now you can process the pickle files." 89 | 90 | json: $(IMAGES_PNG) 91 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 92 | @echo 93 | @echo "Build finished; now you can process the JSON files." 94 | 95 | htmlhelp: $(IMAGES_PNG) 96 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 97 | @echo 98 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 99 | ".hhp project file in $(BUILDDIR)/htmlhelp." 100 | 101 | qthelp: $(IMAGES_PNG) 102 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 103 | @echo 104 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 105 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 106 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/ns-3.qhcp" 107 | @echo "To view the help file:" 108 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/ns-3.qhc" 109 | 110 | devhelp: $(IMAGES_PNG) 111 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 112 | @echo 113 | @echo "Build finished." 114 | @echo "To view the help file:" 115 | @echo "# mkdir -p $$HOME/.local/share/devhelp/ns-3" 116 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/ns-3" 117 | @echo "# devhelp" 118 | 119 | epub: $(IMAGES_PNG) 120 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 121 | @echo 122 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 123 | 124 | latex: $(IMAGES_PNG) 125 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 126 | @echo 127 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 128 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 129 | "(use \`make latexpdf' here to do that automatically)." 130 | 131 | latexpdf: $(IMAGES_PNG) 132 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 133 | @echo "Running LaTeX files through pdflatex..." 134 | make -C $(BUILDDIR)/latex all-pdf 135 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 136 | 137 | text: $(IMAGES_PNG) 138 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 139 | @echo 140 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 141 | 142 | man: $(IMAGES_PNG) 143 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 144 | @echo 145 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 146 | 147 | changes: $(IMAGES_PNG) 148 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 149 | @echo 150 | @echo "The overview file is in $(BUILDDIR)/changes." 151 | 152 | linkcheck: $(IMAGES_PNG) 153 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 154 | @echo 155 | @echo "Link check complete; look for any errors in the above output " \ 156 | "or in $(BUILDDIR)/linkcheck/output.txt." 157 | 158 | doctest: $(IMAGES_PNG) 159 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 160 | @echo "Testing of doctests in the sources finished, look at the " \ 161 | "results in $(BUILDDIR)/doctest/output.txt." 162 | 163 | -------------------------------------------------------------------------------- /doc/source/figures/ofswitch13-controller.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ljerezchaves/ofswitch13/a5f02d44c05b1d2a9da49164443d7dc2f6b9fd1c/doc/source/figures/ofswitch13-controller.pdf -------------------------------------------------------------------------------- /doc/source/figures/ofswitch13-module.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ljerezchaves/ofswitch13/a5f02d44c05b1d2a9da49164443d7dc2f6b9fd1c/doc/source/figures/ofswitch13-module.pdf -------------------------------------------------------------------------------- /doc/source/figures/ofswitch13-qos-topology.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ljerezchaves/ofswitch13/a5f02d44c05b1d2a9da49164443d7dc2f6b9fd1c/doc/source/figures/ofswitch13-qos-topology.pdf -------------------------------------------------------------------------------- /doc/source/figures/ofswitch13-switch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ljerezchaves/ofswitch13/a5f02d44c05b1d2a9da49164443d7dc2f6b9fd1c/doc/source/figures/ofswitch13-switch.pdf -------------------------------------------------------------------------------- /doc/source/ofswitch13.rst: -------------------------------------------------------------------------------- 1 | -------------------------------- 2 | OpenFlow 1.3 Module (OFSwitch13) 3 | -------------------------------- 4 | 5 | .. highlight:: cpp 6 | 7 | .. heading hierarchy: 8 | ------------- Chapter 9 | ************* Section (#.#) 10 | ============= Subsection (#.#.#) 11 | ############# Paragraph (no number) 12 | 13 | .. toctree:: 14 | 15 | ofswitch13-description 16 | ofswitch13-usage 17 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | build_lib_example( 2 | NAME ofswitch13-first 3 | SOURCE_FILES ofswitch13-first.cc 4 | LIBRARIES_TO_LINK 5 | ${libofswitch13} 6 | ${libinternet-apps} 7 | ) 8 | 9 | build_lib_example( 10 | NAME ofswitch13-custom-switch 11 | SOURCE_FILES ofswitch13-custom-switch.cc 12 | LIBRARIES_TO_LINK 13 | ${libofswitch13} 14 | ${libinternet-apps} 15 | ) 16 | 17 | build_lib_example( 18 | NAME ofswitch13-multiple-controllers 19 | SOURCE_FILES ofswitch13-multiple-controllers.cc 20 | LIBRARIES_TO_LINK 21 | ${libofswitch13} 22 | ${libinternet-apps} 23 | ) 24 | 25 | build_lib_example( 26 | NAME ofswitch13-multiple-domains 27 | SOURCE_FILES ofswitch13-multiple-domains.cc 28 | LIBRARIES_TO_LINK 29 | ${libofswitch13} 30 | ${libinternet-apps} 31 | ) 32 | 33 | build_lib_example( 34 | NAME ofswitch13-single-domain 35 | SOURCE_FILES ofswitch13-single-domain.cc 36 | LIBRARIES_TO_LINK 37 | ${libofswitch13} 38 | ${libinternet-apps} 39 | ) 40 | 41 | build_lib_example( 42 | NAME ofswitch13-external-controller 43 | SOURCE_FILES ofswitch13-external-controller.cc 44 | LIBRARIES_TO_LINK 45 | ${libofswitch13} 46 | ${libinternet-apps} 47 | ${libtap-bridge} 48 | ) 49 | 50 | build_lib_example( 51 | NAME ofswitch13-qos-controller 52 | SOURCE_FILES ofswitch13-qos-controller/main.cc 53 | ofswitch13-qos-controller/qos-controller.cc 54 | LIBRARIES_TO_LINK 55 | ${libofswitch13} 56 | ${libapplications} 57 | ) 58 | 59 | build_lib_example( 60 | NAME ofswitch13-logical-port 61 | SOURCE_FILES ofswitch13-logical-port/main.cc 62 | ofswitch13-logical-port/tunnel-controller.cc 63 | ofswitch13-logical-port/gtp-tunnel-app.cc 64 | LIBRARIES_TO_LINK 65 | ${libofswitch13} 66 | ${libinternet-apps} 67 | ${liblte} 68 | ) 69 | -------------------------------------------------------------------------------- /examples/ofswitch13-custom-switch.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | /* 21 | * Two hosts connected to a single OpenFlow switch. 22 | * The switch is managed by the default learning controller application. 23 | * The switch datapath can be customized by the command line parameters. 24 | * 25 | * Learning Controller 26 | * | 27 | * +-----------------+ 28 | * Host 0 === | OpenFlow switch | === Host 1 29 | * +-----------------+ 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | using namespace ns3; 40 | 41 | int 42 | main(int argc, char* argv[]) 43 | { 44 | uint16_t simTime = 10; 45 | bool verbose = false; 46 | bool trace = false; 47 | 48 | // Custom switch datapath attributes 49 | uint32_t flowSize = 10; 50 | uint32_t groupSize = 10; 51 | uint32_t meterSize = 10; 52 | uint32_t pipeTabs = 1; 53 | DataRate pipeLoad = DataRate("1Mbps"); 54 | 55 | // Configure command line parameters 56 | CommandLine cmd; 57 | cmd.AddValue("simTime", "Simulation time (seconds)", simTime); 58 | cmd.AddValue("verbose", "Enable verbose output", verbose); 59 | cmd.AddValue("trace", "Enable datapath stats and pcap traces", trace); 60 | cmd.AddValue("flowSize", "The flow table size", flowSize); 61 | cmd.AddValue("groupSize", "The group table size", groupSize); 62 | cmd.AddValue("meterSize", "The meter table size", meterSize); 63 | cmd.AddValue("pipeTabs", "The number of pipeline flow tables", pipeTabs); 64 | cmd.AddValue("pipeLoad", "The pipeline processing capacity", pipeLoad); 65 | cmd.Parse(argc, argv); 66 | 67 | if (verbose) 68 | { 69 | OFSwitch13Helper::EnableDatapathLogs(); 70 | LogComponentEnable("OFSwitch13Interface", LOG_LEVEL_ALL); 71 | LogComponentEnable("OFSwitch13Device", LOG_LEVEL_ALL); 72 | LogComponentEnable("OFSwitch13Port", LOG_LEVEL_ALL); 73 | LogComponentEnable("OFSwitch13Queue", LOG_LEVEL_ALL); 74 | LogComponentEnable("OFSwitch13SocketHandler", LOG_LEVEL_ALL); 75 | LogComponentEnable("OFSwitch13Controller", LOG_LEVEL_ALL); 76 | LogComponentEnable("OFSwitch13LearningController", LOG_LEVEL_ALL); 77 | LogComponentEnable("OFSwitch13Helper", LOG_LEVEL_ALL); 78 | LogComponentEnable("OFSwitch13InternalHelper", LOG_LEVEL_ALL); 79 | } 80 | 81 | 82 | // Create two host nodes 83 | NodeContainer hosts; 84 | hosts.Create(2); 85 | 86 | // Create the switch node 87 | Ptr switchNode = CreateObject(); 88 | 89 | // Use the CsmaHelper to connect host nodes to the switch node 90 | CsmaHelper csmaHelper; 91 | csmaHelper.SetChannelAttribute("DataRate", DataRateValue(DataRate("100Mbps"))); 92 | csmaHelper.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2))); 93 | 94 | NetDeviceContainer hostDevices; 95 | NetDeviceContainer switchPorts; 96 | for (size_t i = 0; i < hosts.GetN(); i++) 97 | { 98 | NodeContainer pair(hosts.Get(i), switchNode); 99 | NetDeviceContainer link = csmaHelper.Install(pair); 100 | hostDevices.Add(link.Get(0)); 101 | switchPorts.Add(link.Get(1)); 102 | } 103 | 104 | // Create the controller node 105 | Ptr controllerNode = CreateObject(); 106 | 107 | // Create the OpenFlow helper with custom switch attributes. 108 | Ptr of13Helper = CreateObject(); 109 | of13Helper->SetDeviceAttribute("CpuCapacity", DataRateValue(pipeLoad)); 110 | of13Helper->SetDeviceAttribute("PipelineTables", UintegerValue(pipeTabs)); 111 | of13Helper->SetDeviceAttribute("FlowTableSize", UintegerValue(flowSize)); 112 | of13Helper->SetDeviceAttribute("GroupTableSize", UintegerValue(groupSize)); 113 | of13Helper->SetDeviceAttribute("MeterTableSize", UintegerValue(meterSize)); 114 | 115 | // Configure the OpenFlow network domain 116 | of13Helper->InstallController(controllerNode); 117 | of13Helper->InstallSwitch(switchNode, switchPorts); 118 | of13Helper->CreateOpenFlowChannels(); 119 | 120 | // Install the TCP/IP stack into hosts nodes 121 | InternetStackHelper internet; 122 | internet.Install(hosts); 123 | 124 | // Set IPv4 host addresses 125 | Ipv4AddressHelper ipv4Helper; 126 | Ipv4InterfaceContainer hostIpIfaces; 127 | ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); 128 | hostIpIfaces = ipv4Helper.Assign(hostDevices); 129 | 130 | // Configure ping application between hosts 131 | PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); 132 | pingHelper.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE)); 133 | ApplicationContainer pingApps = pingHelper.Install(hosts.Get(0)); 134 | pingApps.Start(Seconds(1)); 135 | 136 | // Enable datapath stats and pcap traces at hosts, switch(es), and controller(s) 137 | if (trace) 138 | { 139 | of13Helper->EnableOpenFlowPcap("openflow"); 140 | of13Helper->EnableDatapathStats("switch-stats"); 141 | csmaHelper.EnablePcap("switch", switchPorts, true); 142 | csmaHelper.EnablePcap("host", hostDevices); 143 | } 144 | 145 | // Run the simulation 146 | Simulator::Stop(Seconds(simTime)); 147 | Simulator::Run(); 148 | Simulator::Destroy(); 149 | } 150 | -------------------------------------------------------------------------------- /examples/ofswitch13-external-controller.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 University of Campinas (Unicamp) 3 | * 2020 Federal University of Juiz de Fora (UFJF) 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License version 2 as 7 | * published by the Free Software Foundation; 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | * 18 | * Author: Luciano Jerez Chaves 19 | * Arthur Boechat Mazzi 20 | */ 21 | 22 | /* 23 | * There are N switches connected in line and managed by an external controller. 24 | * There are M hosts equally distributed among the switches. 25 | * Random pings among hosts. 26 | * 27 | * External controller 28 | * | 29 | * +----------------+-------- ... --------+ 30 | * | | | 31 | * +----------+ +----------+ +----------+ 32 | * | Switch 1 | === | Switch 2 | == ... == | Switch N | 33 | * +----------+ +----------+ +----------+ 34 | * || || || 35 | * Hosts Hosts Hosts 36 | * 1, N+1, ... 2, N+2, ... N, 2N, ... 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | using namespace ns3; 48 | 49 | int 50 | main(int argc, char* argv[]) 51 | { 52 | uint16_t simTime = 100; 53 | bool verbose = false; 54 | bool trace = false; 55 | uint16_t numHosts = 20; 56 | uint16_t numSwitches = 3; 57 | uint16_t numPings = 20; 58 | uint16_t pingTime = 10; 59 | 60 | // Configure command line parameters 61 | CommandLine cmd; 62 | cmd.AddValue("simTime", "Simulation time (seconds)", simTime); 63 | cmd.AddValue("verbose", "Enable verbose output", verbose); 64 | cmd.AddValue("trace", "Enable datapath stats and pcap traces", trace); 65 | cmd.AddValue("numHosts", "Number of hosts in the simulation", numHosts); 66 | cmd.AddValue("numSwitches", "Number of switches in the simulation", numSwitches); 67 | cmd.AddValue("numPings", "Number of ping apps int the simulation", numPings); 68 | cmd.AddValue("pingTime", "Ping time (seconds)", pingTime); 69 | cmd.Parse(argc, argv); 70 | 71 | if (verbose) 72 | { 73 | OFSwitch13Helper::EnableDatapathLogs(); 74 | LogComponentEnable("OFSwitch13Interface", LOG_LEVEL_ALL); 75 | LogComponentEnable("OFSwitch13Device", LOG_LEVEL_ALL); 76 | LogComponentEnable("OFSwitch13Port", LOG_LEVEL_ALL); 77 | LogComponentEnable("OFSwitch13Queue", LOG_LEVEL_ALL); 78 | LogComponentEnable("OFSwitch13SocketHandler", LOG_LEVEL_ALL); 79 | LogComponentEnable("OFSwitch13Controller", LOG_LEVEL_ALL); 80 | LogComponentEnable("OFSwitch13LearningController", LOG_LEVEL_ALL); 81 | LogComponentEnable("OFSwitch13Helper", LOG_LEVEL_ALL); 82 | LogComponentEnable("OFSwitch13InternalHelper", LOG_LEVEL_ALL); 83 | } 84 | 85 | 86 | // Set simulator to real time mode 87 | GlobalValue::Bind("SimulatorImplementationType", StringValue("ns3::RealtimeSimulatorImpl")); 88 | 89 | // Create host nodes 90 | NodeContainer hosts; 91 | hosts.Create(numHosts); 92 | 93 | // Create switch nodes 94 | NodeContainer switches; 95 | switches.Create(numSwitches); 96 | 97 | // Use the CsmaHelper to connect host and switch 98 | CsmaHelper csmaHelper; 99 | csmaHelper.SetChannelAttribute("DataRate", DataRateValue(DataRate("100Mbps"))); 100 | csmaHelper.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2))); 101 | 102 | NodeContainer pair; 103 | NetDeviceContainer pairDevs; 104 | NetDeviceContainer hostDevices; 105 | NetDeviceContainer switchPorts[numSwitches]; 106 | for (int i = 0; i < numSwitches; i++) 107 | { 108 | switchPorts[i] = NetDeviceContainer(); 109 | } 110 | 111 | // Connect hosts to switches in round robin 112 | for (size_t i = 0; i < numHosts; i++) 113 | { 114 | int j = i % numSwitches; 115 | pair = NodeContainer(hosts.Get(i), switches.Get(j)); 116 | pairDevs = csmaHelper.Install(pair); 117 | hostDevices.Add(pairDevs.Get(0)); 118 | switchPorts[j].Add(pairDevs.Get(1)); 119 | } 120 | 121 | // Connect the switches in chain 122 | for (int i = 0; i < numSwitches - 1; i++) 123 | { 124 | pair = NodeContainer(switches.Get(i), switches.Get(i + 1)); 125 | pairDevs = csmaHelper.Install(pair); 126 | switchPorts[i].Add(pairDevs.Get(0)); 127 | switchPorts[i + 1].Add(pairDevs.Get(1)); 128 | } 129 | 130 | // Create the controller node 131 | Ptr controllerNode = CreateObject(); 132 | 133 | // Configure the OpenFlow network domain using an external controller 134 | Ptr of13Helper = CreateObject(); 135 | Ptr ctrlDev = of13Helper->InstallExternalController(controllerNode); 136 | for (int i = 0; i < numSwitches; i++) 137 | { 138 | of13Helper->InstallSwitch(switches.Get(i), switchPorts[i]); 139 | } 140 | of13Helper->CreateOpenFlowChannels(); 141 | 142 | // TapBridge the controller device to local machine 143 | // The default configuration expects a controller on local port 6653 144 | TapBridgeHelper tapBridge; 145 | tapBridge.SetAttribute("Mode", StringValue("ConfigureLocal")); 146 | tapBridge.SetAttribute("DeviceName", StringValue("ctrl")); 147 | tapBridge.Install(controllerNode, ctrlDev); 148 | 149 | // Install the TCP/IP stack into hosts nodes 150 | InternetStackHelper internet; 151 | internet.Install(hosts); 152 | 153 | // Set IPv4 host addresses 154 | Ipv4AddressHelper ipv4Helper; 155 | Ipv4InterfaceContainer hostIpIfaces; 156 | ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); 157 | hostIpIfaces = ipv4Helper.Assign(hostDevices); 158 | 159 | // Random number generators for ping applications 160 | Ptr randomHostRng = CreateObject(); 161 | randomHostRng->SetAttribute("Min", DoubleValue(0)); 162 | randomHostRng->SetAttribute("Max", DoubleValue(numHosts - 1)); 163 | 164 | Ptr randomStartRng = CreateObject(); 165 | randomStartRng->SetAttribute("Mean", DoubleValue(20)); 166 | 167 | // Configure ping application between random hosts 168 | Time startTime = Seconds(1); 169 | for (int i = 0; i < numPings; i++) 170 | { 171 | int srcHost = randomHostRng->GetInteger(); 172 | int dstHost = randomHostRng->GetInteger(); 173 | 174 | PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(dstHost))); 175 | pingHelper.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE)); 176 | Ptr pingApp = pingHelper.Install(hosts.Get(srcHost)).Get(0); 177 | 178 | startTime += Seconds(std::abs(randomStartRng->GetValue())); 179 | pingApp->SetStartTime(startTime); 180 | pingApp->SetStopTime(startTime + Seconds(pingTime)); 181 | } 182 | 183 | // Enable datapath stats and pcap traces at hosts, switch(es), and controller(s) 184 | if (trace) 185 | { 186 | of13Helper->EnableOpenFlowPcap("openflow"); 187 | of13Helper->EnableDatapathStats("switch-stats"); 188 | csmaHelper.EnablePcap("host", hostDevices); 189 | for (int i = 0; i < numSwitches; i++) 190 | { 191 | csmaHelper.EnablePcap("switch", switchPorts[i], true); 192 | } 193 | } 194 | 195 | // Run the simulation 196 | Simulator::Stop(Seconds(simTime)); 197 | Simulator::Run(); 198 | Simulator::Destroy(); 199 | } 200 | -------------------------------------------------------------------------------- /examples/ofswitch13-first.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | * Vitor M. Eichemberger 19 | */ 20 | 21 | /* 22 | * Two hosts connected to a single OpenFlow switch. 23 | * The switch is managed by the default learning controller application. 24 | * 25 | * Learning Controller 26 | * | 27 | * +-----------------+ 28 | * Host 0 === | OpenFlow switch | === Host 1 29 | * +-----------------+ 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | using namespace ns3; 40 | 41 | int 42 | main(int argc, char* argv[]) 43 | { 44 | uint16_t simTime = 10; 45 | bool verbose = false; 46 | bool trace = false; 47 | 48 | // Configure command line parameters 49 | CommandLine cmd; 50 | cmd.AddValue("simTime", "Simulation time (seconds)", simTime); 51 | cmd.AddValue("verbose", "Enable verbose output", verbose); 52 | cmd.AddValue("trace", "Enable datapath stats and pcap traces", trace); 53 | cmd.Parse(argc, argv); 54 | 55 | if (verbose) 56 | { 57 | OFSwitch13Helper::EnableDatapathLogs(); 58 | LogComponentEnable("OFSwitch13Interface", LOG_LEVEL_ALL); 59 | LogComponentEnable("OFSwitch13Device", LOG_LEVEL_ALL); 60 | LogComponentEnable("OFSwitch13Port", LOG_LEVEL_ALL); 61 | LogComponentEnable("OFSwitch13Queue", LOG_LEVEL_ALL); 62 | LogComponentEnable("OFSwitch13SocketHandler", LOG_LEVEL_ALL); 63 | LogComponentEnable("OFSwitch13Controller", LOG_LEVEL_ALL); 64 | LogComponentEnable("OFSwitch13LearningController", LOG_LEVEL_ALL); 65 | LogComponentEnable("OFSwitch13Helper", LOG_LEVEL_ALL); 66 | LogComponentEnable("OFSwitch13InternalHelper", LOG_LEVEL_ALL); 67 | } 68 | 69 | // Create two host nodes 70 | NodeContainer hosts; 71 | hosts.Create(2); 72 | 73 | // Create the switch node 74 | Ptr switchNode = CreateObject(); 75 | 76 | // Use the CsmaHelper to connect host nodes to the switch node 77 | CsmaHelper csmaHelper; 78 | csmaHelper.SetChannelAttribute("DataRate", DataRateValue(DataRate("100Mbps"))); 79 | csmaHelper.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2))); 80 | 81 | NetDeviceContainer hostDevices; 82 | NetDeviceContainer switchPorts; 83 | for (size_t i = 0; i < hosts.GetN(); i++) 84 | { 85 | NodeContainer pair(hosts.Get(i), switchNode); 86 | NetDeviceContainer link = csmaHelper.Install(pair); 87 | hostDevices.Add(link.Get(0)); 88 | switchPorts.Add(link.Get(1)); 89 | } 90 | 91 | // Create the controller node 92 | Ptr controllerNode = CreateObject(); 93 | 94 | // Configure the OpenFlow network domain 95 | Ptr of13Helper = CreateObject(); 96 | of13Helper->InstallController(controllerNode); 97 | of13Helper->InstallSwitch(switchNode, switchPorts); 98 | of13Helper->CreateOpenFlowChannels(); 99 | 100 | // Install the TCP/IP stack into hosts nodes 101 | InternetStackHelper internet; 102 | internet.Install(hosts); 103 | 104 | // Set IPv4 host addresses 105 | Ipv4AddressHelper ipv4Helper; 106 | Ipv4InterfaceContainer hostIpIfaces; 107 | ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); 108 | hostIpIfaces = ipv4Helper.Assign(hostDevices); 109 | 110 | // Configure ping application between hosts 111 | PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); 112 | pingHelper.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE)); 113 | ApplicationContainer pingApps = pingHelper.Install(hosts.Get(0)); 114 | pingApps.Start(Seconds(1)); 115 | 116 | // Enable datapath stats and pcap traces at hosts, switch(es), and controller(s) 117 | if (trace) 118 | { 119 | of13Helper->EnableOpenFlowPcap("openflow"); 120 | of13Helper->EnableDatapathStats("switch-stats"); 121 | csmaHelper.EnablePcap("switch", switchPorts, true); 122 | csmaHelper.EnablePcap("host", hostDevices); 123 | } 124 | 125 | // Run the simulation 126 | Simulator::Stop(Seconds(simTime)); 127 | Simulator::Run(); 128 | Simulator::Destroy(); 129 | } 130 | -------------------------------------------------------------------------------- /examples/ofswitch13-logical-port/gtp-tunnel-app.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #include "gtp-tunnel-app.h" 21 | 22 | #include 23 | #include 24 | 25 | namespace ns3 26 | { 27 | 28 | NS_LOG_COMPONENT_DEFINE("GtpTunnelApp"); 29 | NS_OBJECT_ENSURE_REGISTERED(GtpTunnelApp); 30 | 31 | GtpTunnelApp::GtpTunnelApp(Ptr logicalPort, Ptr physicalDev) 32 | { 33 | NS_LOG_FUNCTION(this << logicalPort << physicalDev); 34 | 35 | // Save the pointers and set the send callback. 36 | m_logicalPort = logicalPort; 37 | m_logicalPort->SetSendCallback(MakeCallback(&GtpTunnelApp::RecvFromLogicalPort, this)); 38 | m_physicalDev = physicalDev; 39 | } 40 | 41 | GtpTunnelApp::~GtpTunnelApp() 42 | { 43 | NS_LOG_FUNCTION(this); 44 | } 45 | 46 | TypeId 47 | GtpTunnelApp::GetTypeId() 48 | { 49 | // clang-format off 50 | static TypeId tid = TypeId("ns3::GtpTunnelApp") 51 | .SetParent() 52 | .SetGroupName("OFSwitch13"); 53 | return tid; 54 | // clang-format on 55 | } 56 | 57 | bool 58 | GtpTunnelApp::RecvFromLogicalPort(Ptr packet, 59 | const Address& source, 60 | const Address& dest, 61 | uint16_t protocolNo) 62 | { 63 | NS_LOG_FUNCTION(this << packet << source << dest << protocolNo); 64 | 65 | // Remove the TunnelId tag with TEID value and destination address. 66 | TunnelIdTag tunnelIdTag; 67 | bool foud = packet->RemovePacketTag(tunnelIdTag); 68 | NS_ASSERT_MSG(foud, "Expected TunnelId tag not found."); 69 | 70 | // We expect that the destination address will be available in the 32 MSB of 71 | // tunnelId, while the TEID will be available in the 32 LSB of tunnelId. 72 | uint64_t tagValue = tunnelIdTag.GetTunnelId(); 73 | uint32_t teid = tagValue; 74 | Ipv4Address ipv4Addr(tagValue >> 32); 75 | InetSocketAddress inetAddr(ipv4Addr, m_port); 76 | 77 | // Add the GTP header. 78 | GtpuHeader gtpu; 79 | gtpu.SetTeid(teid); 80 | gtpu.SetLength(packet->GetSize() + gtpu.GetSerializedSize() - 8); 81 | packet->AddHeader(gtpu); 82 | 83 | NS_LOG_DEBUG("Send packet " << packet->GetUid() << " to tunnel with TEID " << teid << " IP " 84 | << ipv4Addr << " port " << m_port); 85 | 86 | // Send the packet to the tunnel socket. 87 | int bytes = m_tunnelSocket->SendTo(packet, 0, inetAddr); 88 | if (bytes != static_cast(packet->GetSize())) 89 | { 90 | NS_LOG_ERROR("Not all bytes were copied to the socket buffer."); 91 | return false; 92 | } 93 | return true; 94 | } 95 | 96 | void 97 | GtpTunnelApp::RecvFromTunnelSocket(Ptr socket) 98 | { 99 | NS_LOG_FUNCTION(this << socket); 100 | 101 | NS_ASSERT(socket == m_tunnelSocket); 102 | Ptr packet = socket->Recv(); 103 | 104 | // Remove the GTP header. 105 | GtpuHeader gtpu; 106 | packet->RemoveHeader(gtpu); 107 | NS_LOG_DEBUG("Received packet " << packet->GetUid() << " from tunnel with TEID " 108 | << gtpu.GetTeid()); 109 | 110 | // Attach the TunnelId tag with TEID value. 111 | TunnelIdTag tunnelIdTag(gtpu.GetTeid()); 112 | packet->ReplacePacketTag(tunnelIdTag); 113 | 114 | // Add the Ethernet header to the packet, using the physical device MAC 115 | // address as source. Note that the original Ethernet frame was removed by 116 | // the physical device when this packet arrived at this node, so here we 117 | // don't now the original MAC source and destination addresses. The 118 | // destination address must be set to the packet by the OpenFlow pipeline, 119 | // and the source address we set here using the physical device. 120 | AddHeader(packet, Mac48Address::ConvertFrom(m_physicalDev->GetAddress())); 121 | 122 | // Send the packet to the OpenFlow switch over the logical port. Don't worry 123 | // about source and destination addresses because they are note used by the 124 | // receive method. 125 | m_logicalPort->Receive(packet, 126 | Ipv4L3Protocol::PROT_NUMBER, 127 | Mac48Address(), 128 | Mac48Address(), 129 | NetDevice::PACKET_HOST); 130 | } 131 | 132 | void 133 | GtpTunnelApp::DoDispose() 134 | { 135 | NS_LOG_FUNCTION(this); 136 | 137 | m_tunnelSocket = nullptr; 138 | m_logicalPort = nullptr; 139 | m_physicalDev = nullptr; 140 | } 141 | 142 | void 143 | GtpTunnelApp::StartApplication() 144 | { 145 | NS_LOG_FUNCTION(this); 146 | 147 | // Get the physical device address to bind the UDP socket. 148 | Ptr node = m_physicalDev->GetNode(); 149 | Ptr ipv4 = node->GetObject(); 150 | int32_t idx = ipv4->GetInterfaceForDevice(m_physicalDev); 151 | Ipv4Address ipv4Addr = ipv4->GetAddress(idx, 0).GetLocal(); 152 | 153 | // Create and open the UDP socket for tunnel. 154 | m_tunnelSocket = Socket::CreateSocket(GetNode(), TypeId::LookupByName("ns3::UdpSocketFactory")); 155 | m_tunnelSocket->Bind(InetSocketAddress(ipv4Addr, m_port)); 156 | m_tunnelSocket->BindToNetDevice(m_physicalDev); 157 | m_tunnelSocket->SetRecvCallback(MakeCallback(&GtpTunnelApp::RecvFromTunnelSocket, this)); 158 | } 159 | 160 | void 161 | GtpTunnelApp::AddHeader(Ptr packet, 162 | Mac48Address source, 163 | Mac48Address dest, 164 | uint16_t protocolNo) 165 | { 166 | NS_LOG_FUNCTION(this << packet << source << dest << protocolNo); 167 | 168 | // All Ethernet frames must carry a minimum payload of 46 bytes. We need to 169 | // pad out if we don't have enough bytes. These must be real bytes since 170 | // they will be written to pcap files and compared in regression trace 171 | // files. 172 | if (packet->GetSize() < 46) 173 | { 174 | uint8_t buffer[46]; 175 | memset(buffer, 0, 46); 176 | Ptr padd = Create(buffer, 46 - packet->GetSize()); 177 | packet->AddAtEnd(padd); 178 | } 179 | 180 | EthernetHeader header(false); 181 | header.SetSource(source); 182 | header.SetDestination(dest); 183 | header.SetLengthType(protocolNo); 184 | packet->AddHeader(header); 185 | 186 | EthernetTrailer trailer; 187 | if (Node::ChecksumEnabled()) 188 | { 189 | trailer.EnableFcs(true); 190 | } 191 | trailer.CalcFcs(packet); 192 | packet->AddTrailer(trailer); 193 | } 194 | 195 | } // namespace ns3 196 | -------------------------------------------------------------------------------- /examples/ofswitch13-logical-port/gtp-tunnel-app.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef GTP_TUNNEL_APP_H 21 | #define GTP_TUNNEL_APP_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace ns3 31 | { 32 | 33 | /** 34 | * This GTP tunnel application is responsible for implementing the logical port 35 | * operations to encapsulate and de-encapsulated packets withing GTP tunnel. It 36 | * provides the callback implementations that are used by the logical switch 37 | * port and UDP socket. This application is stateless: it only adds/removes 38 | * protocols headers over packets leaving/entering the OpenFlow switch based on 39 | * information that is carried by packet tags. 40 | * 41 | * When sending a packet to the GTP tunnel, this application expects that the 42 | * packet carries the TunnelId tag set with the destination address in the 32 43 | * MSB and the TEID in the 32 LSB of packet tag. When a packet is received from 44 | * the GTP tunnel, this application attachs the TunnelId tag only with the GTP 45 | * TEID value. 46 | */ 47 | class GtpTunnelApp : public Application 48 | { 49 | public: 50 | /** 51 | * Complete constructor. 52 | * \param logicalPort The OpenFlow logical port device. 53 | * \param physicalDev The physical network device on node. 54 | */ 55 | GtpTunnelApp(Ptr logicalPort, Ptr physicalDev); 56 | ~GtpTunnelApp() override; //!< Dummy destructor, see DoDispose. 57 | 58 | /** 59 | * Register this type. 60 | * \return The object TypeId. 61 | */ 62 | static TypeId GetTypeId(); 63 | 64 | /** 65 | * Method to be assigned to the send callback of the VirtualNetDevice 66 | * implementing the OpenFlow logical port. It is called when the OpenFlow 67 | * switch sends a packet out over the logical port. The logical port 68 | * callbacks here, and we must encapsulate the packet withing GTP and 69 | * forward it to the UDP tunnel socket. 70 | * \param packet The packet received from the logical port. 71 | * \param source Ethernet source address. 72 | * \param dest Ethernet destination address. 73 | * \param protocolNo The type of payload contained in this packet. 74 | * \return Whether the operation succeeded. 75 | */ 76 | bool RecvFromLogicalPort(Ptr packet, 77 | const Address& source, 78 | const Address& dest, 79 | uint16_t protocolNo); 80 | 81 | /** 82 | * Method to be assigned to the receive callback of the UDP tunnel socket. 83 | * It is called when the tunnel socket receives a packet, and must forward 84 | * the packet to the logical port. 85 | * \param socket Pointer to the tunnel socket. 86 | */ 87 | void RecvFromTunnelSocket(Ptr socket); 88 | 89 | protected: 90 | /** Destructor implementation. */ 91 | void DoDispose() override; 92 | 93 | // Inherited from Application. 94 | void StartApplication() override; 95 | 96 | private: 97 | /** 98 | * Adds the necessary Ethernet headers and trailers to a packet of data. 99 | * \param packet Packet to which header should be added. 100 | * \param source MAC source address from which packet should be sent. 101 | * \param dest MAC destination address to which packet should be sent. 102 | * \param protocolNo The type of payload contained in this packet. 103 | */ 104 | void AddHeader(Ptr packet, 105 | Mac48Address source = Mac48Address(), 106 | Mac48Address dest = Mac48Address(), 107 | uint16_t protocolNo = Ipv4L3Protocol::PROT_NUMBER); 108 | 109 | Ptr m_tunnelSocket; //!< UDP tunnel socket. 110 | Ptr m_logicalPort; //!< OpenFlow logical port device. 111 | Ptr m_physicalDev; //!< Node physical network device. 112 | const uint16_t m_port = 2152; //!< GTP tunnel port. 113 | }; 114 | 115 | } // namespace ns3 116 | #endif /* GTP_TUNNEL_APP_H */ 117 | -------------------------------------------------------------------------------- /examples/ofswitch13-logical-port/tunnel-controller.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef TUNNEL_CONTROLLER_H 21 | #define TUNNEL_CONTROLLER_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | namespace ns3 31 | { 32 | 33 | /** 34 | * This controller is responsible for installing the forwarding rules on the 35 | * switches. For packets entering the switches coming from the hosts, the 36 | * controller sets the tunnel id and send packets to the logical port, where 37 | * they will be encapsulated withing GTP-U/UDP/IP protocols. For packets 38 | * entering the switches coming from the logical port, the controller forwards 39 | * the packets to the host. 40 | */ 41 | class TunnelController : public OFSwitch13Controller 42 | { 43 | public: 44 | TunnelController(); //!< Default constructor. 45 | ~TunnelController() override; //!< Dummy destructor, see DoDispose. 46 | 47 | /** 48 | * Register this type. 49 | * \return The object TypeId. 50 | */ 51 | static TypeId GetTypeId(); 52 | 53 | /** 54 | * Save the pair IP / MAC address in ARP table. 55 | * \param ipAddr The IPv4 address. 56 | * \param macAddr The MAC address. 57 | */ 58 | void SaveArpEntry(Ipv4Address ipAddr, Mac48Address macAddr); 59 | 60 | /** 61 | * Save the pair datapath ID + port no / IP address in tunnel endpoint table. 62 | * \param dpId The datapath ID. 63 | * \param portNo The port number. 64 | * \param ipAddr The IPv4 address of tunnel endpoint. 65 | */ 66 | void SaveTunnelEndpoint(uint64_t dpId, uint32_t portNo, Ipv4Address ipAddr); 67 | 68 | protected: 69 | /** Destructor implementation */ 70 | void DoDispose() override; 71 | 72 | // Inherited from OFSwitch13Controller 73 | void HandshakeSuccessful(Ptr swtch) override; 74 | 75 | /** 76 | * Handle a packet in message sent by the switch to this controller. 77 | * \note Inherited from OFSwitch13Controller. 78 | * \param msg The OpenFlow received message. 79 | * \param swtch The remote switch metadata. 80 | * \param xid The transaction id from the request message. 81 | * \return 0 if everything's ok, otherwise an error number. 82 | */ 83 | ofl_err HandlePacketIn(struct ofl_msg_packet_in* msg, 84 | Ptr swtch, 85 | uint32_t xid) override; 86 | 87 | private: 88 | /** 89 | * Perform ARP resolution. 90 | * \param ip The Ipv4Address to search. 91 | * \return The MAC address for this ip. 92 | */ 93 | Mac48Address GetArpEntry(Ipv4Address ip); 94 | 95 | /** 96 | * Perform tunnel endpoint resolution. 97 | * \param dpId The datapath ID. 98 | * \param portNo The port number. 99 | * \return The IPv4 address of tunnel endpoint. 100 | */ 101 | Ipv4Address GetTunnelEndpoint(uint64_t dpId, uint32_t portNo); 102 | 103 | /** 104 | * Handle packet-in messages sent from switch with ARP message. 105 | * \param msg The packet-in message. 106 | * \param swtch The switch information. 107 | * \param xid Transaction id. 108 | * \return 0 if everything's ok, otherwise an error number. 109 | */ 110 | ofl_err HandleArpPacketIn(struct ofl_msg_packet_in* msg, 111 | Ptr swtch, 112 | uint32_t xid); 113 | 114 | /** 115 | * Extract an IPv4 address from packet match. 116 | * \param oxm_of The OXM_IF_* IPv4 field. 117 | * \param match The ofl_match structure pointer. 118 | * \return The IPv4 address. 119 | */ 120 | Ipv4Address ExtractIpv4Address(uint32_t oxm_of, struct ofl_match* match); 121 | 122 | /** 123 | * Create a Packet with an ARP reply, encapsulated inside of an Ethernet 124 | * frame (with header and trailer. 125 | * \param srcMac Source MAC address. 126 | * \param srcIp Source IP address. 127 | * \param dstMac Destination MAC address. 128 | * \param dstIp Destination IP address. 129 | * \return The ns3 Ptr with the ARP reply. 130 | */ 131 | Ptr CreateArpReply(Mac48Address srcMac, 132 | Ipv4Address srcIp, 133 | Mac48Address dstMac, 134 | Ipv4Address dstIp); 135 | 136 | /** A pair identifying OpenFlow datapath id and port number. */ 137 | typedef std::pair DpPortPair_t; 138 | 139 | /** Map saving */ 140 | typedef std::map DpPortIpMap_t; 141 | 142 | /** Map saving */ 143 | typedef std::map IpMacMap_t; 144 | 145 | IpMacMap_t m_arpTable; //!< ARP resolution table. 146 | DpPortIpMap_t m_endpointTable; //!< Tunnel endpoint resolution table. 147 | }; 148 | 149 | } // namespace ns3 150 | #endif /* TUNNEL_CONTROLLER_H */ 151 | -------------------------------------------------------------------------------- /examples/ofswitch13-multiple-controllers.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | /* 21 | * Two hosts connected to a single OpenFlow switch. 22 | * The switch is managed by to different controllers applications (Controllers 0 and 1). 23 | * 24 | * Controller 0 Controller 1 25 | * | | 26 | * +-------------+ 27 | * | 28 | * +-----------------+ 29 | * Host 0 === | OpenFlow switch | === Host 1 30 | * +-----------------+ 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | using namespace ns3; 41 | 42 | class Controller0; 43 | class Controller1; 44 | 45 | int 46 | main(int argc, char* argv[]) 47 | { 48 | uint16_t simTime = 10; 49 | bool verbose = false; 50 | bool trace = false; 51 | 52 | // Configure command line parameters 53 | CommandLine cmd; 54 | cmd.AddValue("simTime", "Simulation time (seconds)", simTime); 55 | cmd.AddValue("verbose", "Enable verbose output", verbose); 56 | cmd.AddValue("trace", "Enable datapath stats and pcap traces", trace); 57 | cmd.Parse(argc, argv); 58 | 59 | if (verbose) 60 | { 61 | OFSwitch13Helper::EnableDatapathLogs(); 62 | LogComponentEnable("OFSwitch13Interface", LOG_LEVEL_ALL); 63 | LogComponentEnable("OFSwitch13Device", LOG_LEVEL_ALL); 64 | LogComponentEnable("OFSwitch13Port", LOG_LEVEL_ALL); 65 | LogComponentEnable("OFSwitch13Queue", LOG_LEVEL_ALL); 66 | LogComponentEnable("OFSwitch13SocketHandler", LOG_LEVEL_ALL); 67 | LogComponentEnable("OFSwitch13Controller", LOG_LEVEL_ALL); 68 | LogComponentEnable("OFSwitch13LearningController", LOG_LEVEL_ALL); 69 | LogComponentEnable("OFSwitch13Helper", LOG_LEVEL_ALL); 70 | LogComponentEnable("OFSwitch13InternalHelper", LOG_LEVEL_ALL); 71 | } 72 | 73 | // Create two host nodes 74 | NodeContainer hosts; 75 | hosts.Create(2); 76 | 77 | // Create the switch node 78 | Ptr switchNode = CreateObject(); 79 | 80 | // Use the CsmaHelper to connect host nodes to the switch node 81 | CsmaHelper csmaHelper; 82 | csmaHelper.SetChannelAttribute("DataRate", DataRateValue(DataRate("100Mbps"))); 83 | csmaHelper.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2))); 84 | 85 | NetDeviceContainer hostDevices; 86 | NetDeviceContainer switchPorts; 87 | for (size_t i = 0; i < hosts.GetN(); i++) 88 | { 89 | NodeContainer pair(hosts.Get(i), switchNode); 90 | NetDeviceContainer link = csmaHelper.Install(pair); 91 | hostDevices.Add(link.Get(0)); 92 | switchPorts.Add(link.Get(1)); 93 | } 94 | 95 | // Create two controller nodes 96 | NodeContainer controllers; 97 | controllers.Create(2); 98 | 99 | // Configure the OpenFlow network domain 100 | Ptr of13Helper = CreateObject(); 101 | Ptr ctrl0 = CreateObject(); 102 | Ptr ctrl1 = CreateObject(); 103 | of13Helper->InstallController(controllers.Get(0), ctrl0); 104 | of13Helper->InstallController(controllers.Get(1), ctrl1); 105 | of13Helper->InstallSwitch(switchNode, switchPorts); 106 | of13Helper->CreateOpenFlowChannels(); 107 | 108 | // Install the TCP/IP stack into hosts nodes 109 | InternetStackHelper internet; 110 | internet.Install(hosts); 111 | 112 | // Set IPv4 host addresses 113 | Ipv4AddressHelper ipv4Helper; 114 | Ipv4InterfaceContainer hostIpIfaces; 115 | ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); 116 | hostIpIfaces = ipv4Helper.Assign(hostDevices); 117 | 118 | // Configure ping application between hosts 119 | PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); 120 | pingHelper.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE)); 121 | ApplicationContainer pingApps = pingHelper.Install(hosts.Get(0)); 122 | pingApps.Start(Seconds(1)); 123 | 124 | // Enable datapath stats and pcap traces at hosts, switch(es), and controller(s) 125 | if (trace) 126 | { 127 | of13Helper->EnableOpenFlowPcap("openflow"); 128 | of13Helper->EnableDatapathStats("switch-stats"); 129 | csmaHelper.EnablePcap("switch", switchPorts, true); 130 | csmaHelper.EnablePcap("host", hostDevices); 131 | } 132 | 133 | // Run the simulation 134 | Simulator::Stop(Seconds(simTime)); 135 | Simulator::Run(); 136 | Simulator::Destroy(); 137 | } 138 | 139 | /** Controller 0 installs the rule to forward packets from host 0 to 1 (port 1 to 2). */ 140 | class Controller0 : public OFSwitch13Controller 141 | { 142 | protected: 143 | // Inherited from OFSwitch13Controller 144 | void HandshakeSuccessful(Ptr swtch) override; 145 | }; 146 | 147 | void 148 | Controller0::HandshakeSuccessful(Ptr swtch) 149 | { 150 | DpctlExecute(swtch->GetDpId(), "flow-mod cmd=add,table=0,prio=1 in_port=1 write:output=2"); 151 | } 152 | 153 | /** Controller 1 installs the rule to forward packets from host 1 to 0 (port 2 to 1). */ 154 | class Controller1 : public OFSwitch13Controller 155 | { 156 | protected: 157 | // Inherited from OFSwitch13Controller 158 | void HandshakeSuccessful(Ptr swtch) override; 159 | }; 160 | 161 | void 162 | Controller1::HandshakeSuccessful(Ptr swtch) 163 | { 164 | DpctlExecute(swtch->GetDpId(), "flow-mod cmd=add,table=0,prio=1 in_port=2 write:output=1"); 165 | } 166 | -------------------------------------------------------------------------------- /examples/ofswitch13-multiple-domains.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | * Vitor M. Eichemberger 19 | */ 20 | 21 | /* 22 | * Two hosts connected to different OpenFlow switches. 23 | * Each switch is managed by an independent default learning controller application. 24 | * 25 | * Learning Controller Learning Controller 26 | * | | 27 | * +----------+ +----------+ 28 | * Host 0 === | Switch 0 | ======== | Switch 1 | === Host 1 29 | * +----------+ +----------+ 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | using namespace ns3; 40 | 41 | int 42 | main(int argc, char* argv[]) 43 | { 44 | uint16_t simTime = 10; 45 | bool verbose = false; 46 | bool trace = false; 47 | 48 | // Configure command line parameters 49 | CommandLine cmd; 50 | cmd.AddValue("simTime", "Simulation time (seconds)", simTime); 51 | cmd.AddValue("verbose", "Enable verbose output", verbose); 52 | cmd.AddValue("trace", "Enable datapath stats and pcap traces", trace); 53 | cmd.Parse(argc, argv); 54 | 55 | if (verbose) 56 | { 57 | OFSwitch13Helper::EnableDatapathLogs(); 58 | LogComponentEnable("OFSwitch13Interface", LOG_LEVEL_ALL); 59 | LogComponentEnable("OFSwitch13Device", LOG_LEVEL_ALL); 60 | LogComponentEnable("OFSwitch13Port", LOG_LEVEL_ALL); 61 | LogComponentEnable("OFSwitch13Queue", LOG_LEVEL_ALL); 62 | LogComponentEnable("OFSwitch13SocketHandler", LOG_LEVEL_ALL); 63 | LogComponentEnable("OFSwitch13Controller", LOG_LEVEL_ALL); 64 | LogComponentEnable("OFSwitch13LearningController", LOG_LEVEL_ALL); 65 | LogComponentEnable("OFSwitch13Helper", LOG_LEVEL_ALL); 66 | LogComponentEnable("OFSwitch13InternalHelper", LOG_LEVEL_ALL); 67 | } 68 | 69 | // Create two host nodes 70 | NodeContainer hosts; 71 | hosts.Create(2); 72 | 73 | // Create two switch nodes 74 | NodeContainer switches; 75 | switches.Create(2); 76 | 77 | // Use the CsmaHelper to connect hosts and switches 78 | CsmaHelper csmaHelper; 79 | csmaHelper.SetChannelAttribute("DataRate", DataRateValue(DataRate("100Mbps"))); 80 | csmaHelper.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2))); 81 | 82 | NodeContainer pair; 83 | NetDeviceContainer pairDevs; 84 | NetDeviceContainer hostDevices; 85 | NetDeviceContainer switchPorts[2]; 86 | switchPorts[0] = NetDeviceContainer(); 87 | switchPorts[1] = NetDeviceContainer(); 88 | 89 | // Connect host 0 to first switch 90 | pair = NodeContainer(hosts.Get(0), switches.Get(0)); 91 | pairDevs = csmaHelper.Install(pair); 92 | hostDevices.Add(pairDevs.Get(0)); 93 | switchPorts[0].Add(pairDevs.Get(1)); 94 | 95 | // Connect host 1 to second switch 96 | pair = NodeContainer(hosts.Get(1), switches.Get(1)); 97 | pairDevs = csmaHelper.Install(pair); 98 | hostDevices.Add(pairDevs.Get(0)); 99 | switchPorts[1].Add(pairDevs.Get(1)); 100 | 101 | // Connect the switches 102 | pair = NodeContainer(switches.Get(0), switches.Get(1)); 103 | pairDevs = csmaHelper.Install(pair); 104 | switchPorts[0].Add(pairDevs.Get(0)); 105 | switchPorts[1].Add(pairDevs.Get(1)); 106 | 107 | // Create two controller nodes 108 | NodeContainer controllers; 109 | controllers.Create(2); 110 | 111 | // Configure both OpenFlow network domains 112 | Ptr of13Helper0 = CreateObject(); 113 | of13Helper0->InstallController(controllers.Get(0)); 114 | of13Helper0->InstallSwitch(switches.Get(0), switchPorts[0]); 115 | of13Helper0->CreateOpenFlowChannels(); 116 | 117 | Ptr of13Helper1 = CreateObject(); 118 | of13Helper1->InstallController(controllers.Get(1)); 119 | of13Helper1->InstallSwitch(switches.Get(1), switchPorts[1]); 120 | of13Helper1->CreateOpenFlowChannels(); 121 | 122 | // Install the TCP/IP stack into hosts nodes 123 | InternetStackHelper internet; 124 | internet.Install(hosts); 125 | 126 | // Set IPv4 host addresses 127 | Ipv4AddressHelper ipv4Helper; 128 | Ipv4InterfaceContainer hostIpIfaces; 129 | ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); 130 | hostIpIfaces = ipv4Helper.Assign(hostDevices); 131 | 132 | // Configure ping application between hosts 133 | PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); 134 | pingHelper.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE)); 135 | ApplicationContainer pingApps = pingHelper.Install(hosts.Get(0)); 136 | pingApps.Start(Seconds(1)); 137 | 138 | // Enable datapath stats and pcap traces at hosts, switch(es), and controller(s) 139 | if (trace) 140 | { 141 | of13Helper0->EnableOpenFlowPcap("openflow-0"); 142 | of13Helper0->EnableDatapathStats("switch-stats"); 143 | of13Helper1->EnableOpenFlowPcap("openflow-1"); 144 | of13Helper1->EnableDatapathStats("switch-stats"); 145 | csmaHelper.EnablePcap("switch", switchPorts[0], true); 146 | csmaHelper.EnablePcap("switch", switchPorts[1], true); 147 | csmaHelper.EnablePcap("host", hostDevices); 148 | } 149 | 150 | // Run the simulation 151 | Simulator::Stop(Seconds(simTime)); 152 | Simulator::Run(); 153 | Simulator::Destroy(); 154 | } 155 | -------------------------------------------------------------------------------- /examples/ofswitch13-qos-controller/qos-controller.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef QOS_CONTROLLER_H 21 | #define QOS_CONTROLLER_H 22 | 23 | #include 24 | 25 | using namespace ns3; 26 | 27 | /** 28 | * \brief An border OpenFlow 1.3 controller 29 | */ 30 | class QosController : public OFSwitch13Controller 31 | { 32 | public: 33 | QosController(); //!< Default constructor. 34 | ~QosController() override; //!< Dummy destructor. 35 | 36 | /** Destructor implementation */ 37 | void DoDispose() override; 38 | 39 | /** 40 | * Register this type. 41 | * \return The object TypeId. 42 | */ 43 | static TypeId GetTypeId(); 44 | 45 | /** 46 | * Handle a packet in message sent by the switch to this controller. 47 | * \note Inherited from OFSwitch13Controller. 48 | * \param msg The OpenFlow received message. 49 | * \param swtch The remote switch metadata. 50 | * \param xid The transaction id from the request message. 51 | * \return 0 if everything's ok, otherwise an error number. 52 | */ 53 | ofl_err HandlePacketIn(struct ofl_msg_packet_in* msg, 54 | Ptr swtch, 55 | uint32_t xid) override; 56 | 57 | protected: 58 | // Inherited from OFSwitch13Controller 59 | void HandshakeSuccessful(Ptr swtch) override; 60 | 61 | private: 62 | /** 63 | * Configure the border switch. 64 | * \param swtch The switch information. 65 | */ 66 | void ConfigureBorderSwitch(Ptr swtch); 67 | 68 | /** 69 | * Configure the aggregation switch. 70 | * \param swtch The switch information. 71 | */ 72 | void ConfigureAggregationSwitch(Ptr swtch); 73 | 74 | /** 75 | * Handle ARP request messages. 76 | * \param msg The packet-in message. 77 | * \param swtch The switch information. 78 | * \param xid Transaction id. 79 | * \return 0 if everything's ok, otherwise an error number. 80 | */ 81 | ofl_err HandleArpPacketIn(struct ofl_msg_packet_in* msg, 82 | Ptr swtch, 83 | uint32_t xid); 84 | 85 | /** 86 | * Handle TCP connection request 87 | * \param msg The packet-in message. 88 | * \param swtch The switch information. 89 | * \param xid Transaction id. 90 | * \return 0 if everything's ok, otherwise an error number. 91 | */ 92 | ofl_err HandleConnectionRequest(struct ofl_msg_packet_in* msg, 93 | Ptr swtch, 94 | uint32_t xid); 95 | 96 | /** 97 | * Extract an IPv4 address from packet match. 98 | * \param oxm_of The OXM_IF_* IPv4 field. 99 | * \param match The ofl_match structure pointer. 100 | * \return The IPv4 address. 101 | */ 102 | Ipv4Address ExtractIpv4Address(uint32_t oxm_of, struct ofl_match* match); 103 | 104 | /** 105 | * Create an ARP request packet, encapsulated inside of an Ethernet frame. 106 | * \param srcMac Source MAC address. 107 | * \param srcIp Source IP address. 108 | * \param dstIp Destination IP address. 109 | * \return The ns3 Ptr with the ARP request. 110 | */ 111 | Ptr CreateArpRequest(Mac48Address srcMac, Ipv4Address srcIp, Ipv4Address dstIp); 112 | 113 | /** 114 | * Create an ARP reply packet, encapsulated inside of an Ethernet frame. 115 | * \param srcMac Source MAC address. 116 | * \param srcIp Source IP address. 117 | * \param dstMac Destination MAC address. 118 | * \param dstIp Destination IP address. 119 | * \return The ns3 Ptr with the ARP reply. 120 | */ 121 | Ptr CreateArpReply(Mac48Address srcMac, 122 | Ipv4Address srcIp, 123 | Mac48Address dstMac, 124 | Ipv4Address dstIp); 125 | 126 | /** 127 | * Save the pair IP / MAC address in ARP table. 128 | * \param ipAddr The IPv4 address. 129 | * \param macAddr The MAC address. 130 | */ 131 | void SaveArpEntry(Ipv4Address ipAddr, Mac48Address macAddr); 132 | 133 | /** 134 | * Perform an ARP resolution 135 | * \param ip The Ipv4Address to search. 136 | * \return The MAC address for this ip. 137 | */ 138 | Mac48Address GetArpEntry(Ipv4Address ip); 139 | 140 | Address m_serverIpAddress; //!< Virtual server IP address 141 | uint16_t m_serverTcpPort; //!< Virtual server TCP port 142 | Address m_serverMacAddress; //!< Border switch MAC address 143 | bool m_meterEnable; //!< Enable per-flow metering 144 | DataRate m_meterRate; //!< Per-flow meter rate 145 | bool m_linkAggregation; //!< Enable link aggregation 146 | 147 | /** Map saving */ 148 | typedef std::map IpMacMap_t; 149 | IpMacMap_t m_arpTable; //!< ARP resolution table. 150 | }; 151 | 152 | #endif /* QOS_CONTROLLER_H */ 153 | -------------------------------------------------------------------------------- /examples/ofswitch13-single-domain.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | * Vitor M. Eichemberger 19 | */ 20 | 21 | /* 22 | * Two hosts connected to different OpenFlow switches. 23 | * Both switches are managed by the default learning controller application. 24 | * 25 | * Learning Controller 26 | * | 27 | * +-------------+ 28 | * | | 29 | * +----------+ +----------+ 30 | * Host 0 === | Switch 0 | === | Switch 1 | === Host 1 31 | * +----------+ +----------+ 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | using namespace ns3; 42 | 43 | int 44 | main(int argc, char* argv[]) 45 | { 46 | uint16_t simTime = 10; 47 | bool verbose = false; 48 | bool trace = false; 49 | 50 | // Configure command line parameters 51 | CommandLine cmd; 52 | cmd.AddValue("simTime", "Simulation time (seconds)", simTime); 53 | cmd.AddValue("verbose", "Enable verbose output", verbose); 54 | cmd.AddValue("trace", "Enable datapath stats and pcap traces", trace); 55 | cmd.Parse(argc, argv); 56 | 57 | if (verbose) 58 | { 59 | OFSwitch13Helper::EnableDatapathLogs(); 60 | LogComponentEnable("OFSwitch13Interface", LOG_LEVEL_ALL); 61 | LogComponentEnable("OFSwitch13Device", LOG_LEVEL_ALL); 62 | LogComponentEnable("OFSwitch13Port", LOG_LEVEL_ALL); 63 | LogComponentEnable("OFSwitch13Queue", LOG_LEVEL_ALL); 64 | LogComponentEnable("OFSwitch13SocketHandler", LOG_LEVEL_ALL); 65 | LogComponentEnable("OFSwitch13Controller", LOG_LEVEL_ALL); 66 | LogComponentEnable("OFSwitch13LearningController", LOG_LEVEL_ALL); 67 | LogComponentEnable("OFSwitch13Helper", LOG_LEVEL_ALL); 68 | LogComponentEnable("OFSwitch13InternalHelper", LOG_LEVEL_ALL); 69 | } 70 | 71 | // Create two host nodes 72 | NodeContainer hosts; 73 | hosts.Create(2); 74 | 75 | // Create two switch nodes 76 | NodeContainer switches; 77 | switches.Create(2); 78 | 79 | // Use the CsmaHelper to connect hosts and switches 80 | CsmaHelper csmaHelper; 81 | csmaHelper.SetChannelAttribute("DataRate", DataRateValue(DataRate("100Mbps"))); 82 | csmaHelper.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2))); 83 | 84 | NodeContainer pair; 85 | NetDeviceContainer pairDevs; 86 | NetDeviceContainer hostDevices; 87 | NetDeviceContainer switchPorts[2]; 88 | switchPorts[0] = NetDeviceContainer(); 89 | switchPorts[1] = NetDeviceContainer(); 90 | 91 | // Connect host 0 to first switch 92 | pair = NodeContainer(hosts.Get(0), switches.Get(0)); 93 | pairDevs = csmaHelper.Install(pair); 94 | hostDevices.Add(pairDevs.Get(0)); 95 | switchPorts[0].Add(pairDevs.Get(1)); 96 | 97 | // Connect host 1 to second switch 98 | pair = NodeContainer(hosts.Get(1), switches.Get(1)); 99 | pairDevs = csmaHelper.Install(pair); 100 | hostDevices.Add(pairDevs.Get(0)); 101 | switchPorts[1].Add(pairDevs.Get(1)); 102 | 103 | // Connect the switches 104 | pair = NodeContainer(switches.Get(0), switches.Get(1)); 105 | pairDevs = csmaHelper.Install(pair); 106 | switchPorts[0].Add(pairDevs.Get(0)); 107 | switchPorts[1].Add(pairDevs.Get(1)); 108 | 109 | // Create the controller node 110 | Ptr controllerNode = CreateObject(); 111 | 112 | // Configure the OpenFlow network domain 113 | Ptr of13Helper = CreateObject(); 114 | of13Helper->InstallController(controllerNode); 115 | of13Helper->InstallSwitch(switches.Get(0), switchPorts[0]); 116 | of13Helper->InstallSwitch(switches.Get(1), switchPorts[1]); 117 | of13Helper->CreateOpenFlowChannels(); 118 | 119 | // Install the TCP/IP stack into hosts nodes 120 | InternetStackHelper internet; 121 | internet.Install(hosts); 122 | 123 | // Set IPv4 host addresses 124 | Ipv4AddressHelper ipv4Helper; 125 | Ipv4InterfaceContainer hostIpIfaces; 126 | ipv4Helper.SetBase("10.1.1.0", "255.255.255.0"); 127 | hostIpIfaces = ipv4Helper.Assign(hostDevices); 128 | 129 | // Configure ping application between hosts 130 | PingHelper pingHelper(Ipv4Address(hostIpIfaces.GetAddress(1))); 131 | pingHelper.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE)); 132 | ApplicationContainer pingApps = pingHelper.Install(hosts.Get(0)); 133 | pingApps.Start(Seconds(1)); 134 | 135 | // Enable datapath stats and pcap traces at hosts, switch(es), and controller(s) 136 | if (trace) 137 | { 138 | of13Helper->EnableOpenFlowPcap("openflow"); 139 | of13Helper->EnableDatapathStats("switch-stats"); 140 | csmaHelper.EnablePcap("switch", switchPorts[0], true); 141 | csmaHelper.EnablePcap("switch", switchPorts[1], true); 142 | csmaHelper.EnablePcap("host", hostDevices); 143 | } 144 | 145 | // Run the simulation 146 | Simulator::Stop(Seconds(simTime)); 147 | Simulator::Run(); 148 | Simulator::Destroy(); 149 | } 150 | -------------------------------------------------------------------------------- /helper/ofswitch13-device-container.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #include "ofswitch13-device-container.h" 21 | 22 | #include 23 | 24 | namespace ns3 25 | { 26 | 27 | OFSwitch13DeviceContainer::OFSwitch13DeviceContainer() 28 | { 29 | } 30 | 31 | OFSwitch13DeviceContainer::OFSwitch13DeviceContainer(Ptr dev) 32 | { 33 | m_devices.emplace_back(dev); 34 | } 35 | 36 | OFSwitch13DeviceContainer::OFSwitch13DeviceContainer(std::string devName) 37 | { 38 | Ptr dev = Names::Find(devName); 39 | m_devices.emplace_back(dev); 40 | } 41 | 42 | OFSwitch13DeviceContainer::OFSwitch13DeviceContainer(const OFSwitch13DeviceContainer& a, 43 | const OFSwitch13DeviceContainer& b) 44 | { 45 | *this = a; 46 | Add(b); 47 | } 48 | 49 | OFSwitch13DeviceContainer::Iterator 50 | OFSwitch13DeviceContainer::Begin() const 51 | { 52 | return m_devices.begin(); 53 | } 54 | 55 | OFSwitch13DeviceContainer::Iterator 56 | OFSwitch13DeviceContainer::End() const 57 | { 58 | return m_devices.end(); 59 | } 60 | 61 | uint32_t 62 | OFSwitch13DeviceContainer::GetN() const 63 | { 64 | return m_devices.size(); 65 | } 66 | 67 | Ptr 68 | OFSwitch13DeviceContainer::Get(uint32_t i) const 69 | { 70 | return m_devices[i]; 71 | } 72 | 73 | void 74 | OFSwitch13DeviceContainer::Add(OFSwitch13DeviceContainer other) 75 | { 76 | for (Iterator i = other.Begin(); i != other.End(); i++) 77 | { 78 | m_devices.emplace_back(*i); 79 | } 80 | } 81 | 82 | void 83 | OFSwitch13DeviceContainer::Add(Ptr device) 84 | { 85 | m_devices.emplace_back(device); 86 | } 87 | 88 | void 89 | OFSwitch13DeviceContainer::Add(std::string deviceName) 90 | { 91 | Ptr device = Names::Find(deviceName); 92 | m_devices.emplace_back(device); 93 | } 94 | 95 | } // namespace ns3 96 | -------------------------------------------------------------------------------- /helper/ofswitch13-device-container.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef OFSWITCH13_DEVICE_CONTAINER_H 21 | #define OFSWITCH13_DEVICE_CONTAINER_H 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | namespace ns3 29 | { 30 | 31 | /** 32 | * \ingroup ofswitch13 33 | * \brief Holds a vector of ns3::OFSwitch13Device pointers 34 | * 35 | * Typically OpenFlow Devices are aggregated to nodes using the 36 | * OFSwitch13Helper. The helper InstallSwitch* methods takes a NodeContainer 37 | * which holds some number of Ptr. For each of the Nodes in the 38 | * NodeContainer the helper will instantiate an OpenFlow device and aggregate it 39 | * to the node. For each of the devices, the helper also adds the device into a 40 | * Container for later use by the caller. This is that container used to hold 41 | * the Ptr which are instantiated by the device helper. 42 | */ 43 | class OFSwitch13DeviceContainer 44 | { 45 | public: 46 | /// OFSwitch13Device container iterator 47 | typedef std::vector>::const_iterator Iterator; 48 | 49 | /** 50 | * Create an empty OFSwitch13DeviceContainer. 51 | */ 52 | OFSwitch13DeviceContainer(); 53 | 54 | /** 55 | * Create a OFSwitch13DeviceContainer with exactly one device that has 56 | * previously been instantiated. 57 | * \param dev An OpenFlow device to add to the container. 58 | */ 59 | OFSwitch13DeviceContainer(Ptr dev); 60 | 61 | /** 62 | * Create a OFSwitch13DeviceContainer with exactly one device. Create a 63 | * OFSwitch13DeviceContainer with exactly one device which has been 64 | * previously instantiated and assigned a name using the Object name 65 | * service. This OpenFlow device is specified by its assigned name. 66 | * \param devName The name of the device to add to the container. 67 | */ 68 | OFSwitch13DeviceContainer(std::string devName); 69 | 70 | /** 71 | * Create a device container which is a concatenation of the two input 72 | * OFSwitch13DeviceContainers. 73 | * \note A frequently seen idiom that uses these constructors involves the 74 | * implicit conversion by constructor of Ptr. When used, 75 | * two Ptr will be passed to this constructor instead of 76 | * OFSwitch13DeviceContainer&. C++ will notice the implicit conversion path 77 | * that goes through the OFSwitch13DeviceContainer (Ptr 78 | * dev) constructor above. Using this conversion one may provide optionally 79 | * provide arguments of Ptr to these constructors. 80 | * \param a A device container 81 | * \param b Another device container 82 | * 83 | */ 84 | OFSwitch13DeviceContainer(const OFSwitch13DeviceContainer& a, 85 | const OFSwitch13DeviceContainer& b); 86 | 87 | /** 88 | * \brief Get an iterator which refers to the first OpenFlow device in the 89 | * container. 90 | * OpenFlow devices can be retrieved from the container in two ways. First, 91 | * directly by an index into the container, and second, using an iterator. 92 | * This method is used in the iterator method and is typically used in a 93 | * for-loop to run through the devices. 94 | * \code 95 | * OFSwitch13DeviceContainer::Iterator i; 96 | * for (i = container.Begin(); i != container.End(); ++i) 97 | * { 98 | * (*i)->method(); // some OFSwitch13Device method 99 | * } 100 | * \endcode 101 | * \returns an iterator which refers to the first device in the container. 102 | */ 103 | Iterator Begin() const; 104 | 105 | /** 106 | * \brief Get an iterator which indicates past-the-last OpenFlow device in 107 | * the container. 108 | * OpenFlow devices can be retrieved from the container in two ways. First, 109 | * directly by an index into the container, and second, using an iterator. 110 | * This method is used in the iterator method and is typically used in a 111 | * for-loop to run through the devices 112 | * \code 113 | * OFSwitch13DeviceContainer::Iterator i; 114 | * for (i = container.Begin(); i != container.End(); ++i) 115 | * { 116 | * (*i)->method(); // some OFSwitch13Device method 117 | * } 118 | * \endcode 119 | * \returns an iterator which indicates an ending condition for a loop. 120 | */ 121 | Iterator End() const; 122 | 123 | /** 124 | * \brief Get the number of Ptr stored in this container. 125 | * OpenFlow devices can be retrieved from the container in two ways. First, 126 | * directly by an index into the container, and second, using an iterator. 127 | * This method is used in the direct method and is typically used to 128 | * define an ending condition in a for-loop that runs through the stored 129 | * devices 130 | * \code 131 | * uint32_t nDevices = container.GetN(); 132 | * for (uint32_t i = 0 i < nDevices; ++i) 133 | * { 134 | * Ptr p = container.Get(i); 135 | * p->method(); // some OFSwitch13Device method 136 | * } 137 | * \endcode 138 | * \returns the number of Ptr stored in this container. 139 | */ 140 | uint32_t GetN() const; 141 | 142 | /** 143 | * \brief Get the Ptr stored in this container at a given 144 | * index. 145 | * OpenFlow devices can be retrieved from the container in two ways.First, 146 | * directly by an index into the container, and second, using an iterator. 147 | * This method is used in the direct method and is used to retrieve the 148 | * indexed Ptr. 149 | * \code 150 | * uint32_t nDevices = container.GetN(); 151 | * for (uint32_t i = 0 i < nDevices; ++i) 152 | * { 153 | * Ptr p = container.Get(i); 154 | * p->method(); // some OFSwitch13Device method 155 | * } 156 | * \endcode 157 | * \param i the index of the requested device pointer. 158 | * \returns the requested device pointer. 159 | */ 160 | Ptr Get(uint32_t i) const; 161 | 162 | /** 163 | * \brief Append the contents of another OFSwitch13DeviceContainer to the 164 | * end of this container. 165 | * \param other The OFSwitch13DeviceContainer to append. 166 | */ 167 | void Add(OFSwitch13DeviceContainer other); 168 | 169 | /** 170 | * \brief Append a single Ptr to this container. 171 | * \param device The Ptr to append. 172 | */ 173 | void Add(Ptr device); 174 | 175 | /** 176 | * \brief Append to this container the single Ptr referred 177 | * to via its object name service registered name. 178 | * \param deviceName The name of the OFSwitch13Device object to add to the 179 | * container. 180 | */ 181 | void Add(std::string deviceName); 182 | 183 | private: 184 | std::vector> m_devices; //!< OFSwitch13Device pointers 185 | }; 186 | 187 | } // namespace ns3 188 | 189 | #endif /* OFSWITCH13_DEVICE_CONTAINER_H */ 190 | -------------------------------------------------------------------------------- /helper/ofswitch13-external-helper.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifdef NS3_OFSWITCH13 21 | 22 | #include "ofswitch13-external-helper.h" 23 | 24 | #include 25 | 26 | namespace ns3 27 | { 28 | 29 | NS_LOG_COMPONENT_DEFINE("OFSwitch13ExternalHelper"); 30 | NS_OBJECT_ENSURE_REGISTERED(OFSwitch13ExternalHelper); 31 | 32 | class OFSwitch13Controller; 33 | 34 | OFSwitch13ExternalHelper::OFSwitch13ExternalHelper() 35 | { 36 | NS_LOG_FUNCTION(this); 37 | 38 | // Create the common channel for all switches and controllers. 39 | m_csmaChannel = CreateObject(); 40 | } 41 | 42 | OFSwitch13ExternalHelper::~OFSwitch13ExternalHelper() 43 | { 44 | NS_LOG_FUNCTION(this); 45 | } 46 | 47 | TypeId 48 | OFSwitch13ExternalHelper::GetTypeId() 49 | { 50 | static TypeId tid = 51 | TypeId("ns3::OFSwitch13ExternalHelper") 52 | .SetParent() 53 | .SetGroupName("OFSwitch13") 54 | .AddConstructor() 55 | .AddAttribute("Port", 56 | "The port number where controller will be available.", 57 | UintegerValue(6653), 58 | MakeUintegerAccessor(&OFSwitch13ExternalHelper::m_controlPort), 59 | MakeUintegerChecker()); 60 | return tid; 61 | } 62 | 63 | void 64 | OFSwitch13ExternalHelper::SetChannelType(ChannelType type) 65 | { 66 | NS_LOG_FUNCTION(this << type); 67 | 68 | // Check for valid channel type for this helper. 69 | NS_ABORT_MSG_IF(type != OFSwitch13Helper::SINGLE_CSMA, 70 | "Invalid channel type for OFSwitch13ExternalHelper (use SingleCsma)."); 71 | OFSwitch13Helper::SetChannelType(type); 72 | } 73 | 74 | void 75 | OFSwitch13ExternalHelper::SetChannelDataRate(DataRate rate) 76 | { 77 | NS_LOG_FUNCTION(this << rate); 78 | 79 | OFSwitch13Helper::SetChannelDataRate(rate); 80 | m_csmaChannel->SetAttribute("DataRate", DataRateValue(rate)); 81 | } 82 | 83 | void 84 | OFSwitch13ExternalHelper::CreateOpenFlowChannels() 85 | { 86 | NS_LOG_FUNCTION(this); 87 | 88 | NS_LOG_INFO("Creating OpenFlow channels."); 89 | NS_ABORT_MSG_IF(m_blocked, "OpenFlow channels already configured."); 90 | 91 | // Block this helper to avoid further calls to install methods. 92 | m_blocked = true; 93 | 94 | // Enable checksum computations (mandatory for this module) 95 | GlobalValue::Bind("ChecksumEnabled", BooleanValue(true)); 96 | 97 | // Create and start the connections between switches and controllers. 98 | switch (m_channelType) 99 | { 100 | case OFSwitch13ExternalHelper::SINGLE_CSMA: { 101 | NS_LOG_INFO("Attach all switches and controllers to the same CSMA network."); 102 | 103 | // Connecting all switches to the common channel. 104 | NetDeviceContainer switchDevices; 105 | switchDevices = m_csmaHelper.Install(m_switchNodes, m_csmaChannel); 106 | m_ipv4helper.Assign(switchDevices); 107 | InetSocketAddress addr(m_controlAddr, m_controlPort); 108 | 109 | // Start the connections between controller and switches. 110 | OFSwitch13DeviceContainer::Iterator ofDev; 111 | for (ofDev = m_openFlowDevs.Begin(); ofDev != m_openFlowDevs.End(); ofDev++) 112 | { 113 | NS_LOG_INFO("Connect switch " << (*ofDev)->GetDatapathId() << " to controller " 114 | << addr.GetIpv4() << " port " << addr.GetPort()); 115 | Simulator::ScheduleNow(&OFSwitch13Device::StartControllerConnection, *ofDev, addr); 116 | } 117 | m_ipv4helper.NewNetwork(); 118 | break; 119 | } 120 | case OFSwitch13ExternalHelper::DEDICATED_CSMA: 121 | case OFSwitch13ExternalHelper::DEDICATED_P2P: 122 | default: { 123 | NS_ABORT_MSG("Invalid OpenflowChannelType."); 124 | } 125 | } 126 | } 127 | 128 | Ptr 129 | OFSwitch13ExternalHelper::InstallExternalController(Ptr cNode) 130 | { 131 | NS_LOG_FUNCTION(this << cNode); 132 | 133 | NS_LOG_INFO("Installing OpenFlow controller on node " << cNode->GetId()); 134 | NS_ABORT_MSG_IF(m_blocked || m_controlDevs.GetN() != 0, "OpenFlow channel already configured."); 135 | 136 | // Install the TCP/IP stack into controller node. 137 | if (!cNode->GetObject()) 138 | { 139 | m_internet.Install(cNode); 140 | } 141 | 142 | // Connect the controller node to the common channel and configure IP addrs. 143 | m_controlDevs = m_csmaHelper.Install(cNode, m_csmaChannel); 144 | Ipv4InterfaceContainer ctrlIface = m_ipv4helper.Assign(m_controlDevs); 145 | m_controlAddr = ctrlIface.GetAddress(0); 146 | m_controlNode = cNode; 147 | 148 | return m_controlDevs.Get(0); 149 | } 150 | 151 | void 152 | OFSwitch13ExternalHelper::DoDispose() 153 | { 154 | NS_LOG_FUNCTION(this); 155 | 156 | m_csmaChannel = nullptr; 157 | OFSwitch13Helper::DoDispose(); 158 | } 159 | 160 | } // namespace ns3 161 | #endif // NS3_OFSWITCH13 162 | -------------------------------------------------------------------------------- /helper/ofswitch13-external-helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef OFSWITCH13_EXTERNAL_HELPER_H 21 | #define OFSWITCH13_EXTERNAL_HELPER_H 22 | 23 | #include 24 | 25 | namespace ns3 26 | { 27 | 28 | class Node; 29 | class AttributeValue; 30 | class OFSwitch13Controller; 31 | class OFSwitch13LearningController; 32 | 33 | /** 34 | * \ingroup ofswitch13 35 | * 36 | * This helper extends the base class and can be instantiated to create and 37 | * configure an OpenFlow 1.3 network domain composed of one or more OpenFlow 38 | * switches connected to a single external real OpenFlow controller. It brings 39 | * methods for configuring the controller node for TapBridge usage and creating 40 | * the OpenFlow channels. 41 | */ 42 | class OFSwitch13ExternalHelper : public OFSwitch13Helper 43 | { 44 | public: 45 | OFSwitch13ExternalHelper(); //!< Default constructor. 46 | ~OFSwitch13ExternalHelper() override; //!< Dummy destructor, see DoDispose. 47 | 48 | /** 49 | * Register this type. 50 | * \return The object TypeId. 51 | */ 52 | static TypeId GetTypeId(); 53 | 54 | // Inherited from OFSwitch13Helper. 55 | void SetChannelType(ChannelType type) override; 56 | void SetChannelDataRate(DataRate rate) override; 57 | void CreateOpenFlowChannels() override; 58 | 59 | /** 60 | * This method prepares the controller node so it can be used to connect 61 | * internal simulated switches to an external OpenFlow controller running on 62 | * the local machine over a TapBridge device. It installs the TCP/IP stack 63 | * into controller node, attach it to the common CSMA channel and configure 64 | * IP address for it. 65 | * \param cNode The node to configure as the controller. 66 | * \return The network device to bind to the TapBridge. 67 | */ 68 | Ptr InstallExternalController(Ptr cNode); 69 | 70 | protected: 71 | /** Destructor implementation. */ 72 | void DoDispose() override; 73 | 74 | private: 75 | Ptr m_csmaChannel; //!< Common CSMA channel. 76 | Ptr m_controlNode; //!< OF controller node. 77 | uint16_t m_controlPort; //!< OF controller TCP port. 78 | Ipv4Address m_controlAddr; //!< OF IP controller addr. 79 | }; 80 | 81 | } // namespace ns3 82 | #endif /* OFSWITCH13_EXTERNAL_HELPER_H */ 83 | -------------------------------------------------------------------------------- /helper/ofswitch13-helper.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifdef NS3_OFSWITCH13 21 | 22 | #include "ofswitch13-helper.h" 23 | 24 | #include "ofswitch13-stats-calculator.h" 25 | 26 | #include 27 | 28 | namespace ns3 29 | { 30 | 31 | NS_LOG_COMPONENT_DEFINE("OFSwitch13Helper"); 32 | NS_OBJECT_ENSURE_REGISTERED(OFSwitch13Helper); 33 | 34 | Ipv4AddressHelper OFSwitch13Helper::m_ipv4helper = Ipv4AddressHelper("10.100.0.0", "255.255.255.0"); 35 | 36 | class OFSwitch13Controller; 37 | 38 | OFSwitch13Helper::OFSwitch13Helper() 39 | : m_blocked(false) 40 | { 41 | NS_LOG_FUNCTION(this); 42 | 43 | // Set OpenFlow device factory TypeId. 44 | m_devFactory.SetTypeId("ns3::OFSwitch13Device"); 45 | } 46 | 47 | OFSwitch13Helper::~OFSwitch13Helper() 48 | { 49 | NS_LOG_FUNCTION(this); 50 | } 51 | 52 | TypeId 53 | OFSwitch13Helper::GetTypeId() 54 | { 55 | static TypeId tid = 56 | TypeId("ns3::OFSwitch13Helper") 57 | .SetParent() 58 | .SetGroupName("OFSwitch13") 59 | .AddAttribute("ChannelDataRate", 60 | "The data rate to be used for the OpenFlow channel.", 61 | DataRateValue(DataRate("10Gb/s")), 62 | MakeDataRateAccessor(&OFSwitch13Helper::SetChannelDataRate), 63 | MakeDataRateChecker()) 64 | .AddAttribute("ChannelType", 65 | "The configuration used to create the OpenFlow channel", 66 | TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, 67 | EnumValue(OFSwitch13Helper::SINGLE_CSMA), 68 | MakeEnumAccessor(&OFSwitch13Helper::SetChannelType), 69 | MakeEnumChecker(OFSwitch13Helper::SINGLE_CSMA, 70 | "SingleCsma", 71 | OFSwitch13Helper::DEDICATED_CSMA, 72 | "DedicatedCsma", 73 | OFSwitch13Helper::DEDICATED_P2P, 74 | "DedicatedP2p")); 75 | return tid; 76 | } 77 | 78 | void 79 | OFSwitch13Helper::SetDeviceAttribute(std::string n1, const AttributeValue& v1) 80 | { 81 | NS_LOG_FUNCTION(this); 82 | 83 | m_devFactory.Set(n1, v1); 84 | } 85 | 86 | void 87 | OFSwitch13Helper::SetChannelType(ChannelType type) 88 | { 89 | NS_LOG_FUNCTION(this << type); 90 | 91 | // Set the channel type and address, which will select proper network mask. 92 | m_channelType = type; 93 | } 94 | 95 | void 96 | OFSwitch13Helper::SetChannelDataRate(DataRate rate) 97 | { 98 | NS_LOG_FUNCTION(this << rate); 99 | 100 | m_channelDataRate = rate; 101 | } 102 | 103 | void 104 | OFSwitch13Helper::EnableOpenFlowPcap(std::string prefix, bool promiscuous) 105 | { 106 | NS_LOG_FUNCTION(this << prefix); 107 | 108 | NS_ABORT_MSG_IF(!m_blocked, "OpenFlow channels not configured yet."); 109 | switch (m_channelType) 110 | { 111 | case OFSwitch13Helper::SINGLE_CSMA: 112 | case OFSwitch13Helper::DEDICATED_CSMA: { 113 | m_csmaHelper.EnablePcap(prefix, m_controlDevs, promiscuous); 114 | break; 115 | } 116 | case OFSwitch13Helper::DEDICATED_P2P: { 117 | m_p2pHelper.EnablePcap(prefix, m_controlDevs, promiscuous); 118 | break; 119 | } 120 | default: { 121 | NS_ABORT_MSG("Invalid OpenflowChannelType."); 122 | } 123 | } 124 | } 125 | 126 | void 127 | OFSwitch13Helper::EnableOpenFlowAscii(std::string prefix) 128 | { 129 | NS_LOG_FUNCTION(this << prefix); 130 | 131 | NS_ABORT_MSG_IF(!m_blocked, "OpenFlow channels not configured yet."); 132 | AsciiTraceHelper ascii; 133 | switch (m_channelType) 134 | { 135 | case OFSwitch13Helper::SINGLE_CSMA: 136 | case OFSwitch13Helper::DEDICATED_CSMA: { 137 | m_csmaHelper.EnableAsciiAll(ascii.CreateFileStream(prefix + ".txt")); 138 | break; 139 | } 140 | case OFSwitch13Helper::DEDICATED_P2P: { 141 | m_p2pHelper.EnableAsciiAll(ascii.CreateFileStream(prefix + ".txt")); 142 | break; 143 | } 144 | default: { 145 | NS_ABORT_MSG("Invalid OpenflowChannelType."); 146 | } 147 | } 148 | } 149 | 150 | void 151 | OFSwitch13Helper::EnableDatapathStats(std::string prefix, bool useNodeNames) 152 | { 153 | NS_LOG_FUNCTION(this << prefix); 154 | 155 | NS_ABORT_MSG_IF(!m_blocked, "OpenFlow channels not configured yet."); 156 | NS_ASSERT_MSG(prefix.size(), "Empty prefix string."); 157 | if (prefix.back() != '-') 158 | { 159 | prefix += "-"; 160 | } 161 | 162 | ObjectFactory statsFactory("ns3::OFSwitch13StatsCalculator"); 163 | Ptr statsCalculator; 164 | const std::string extension = ".log"; 165 | 166 | // Iterate over the container and for each OpenFlow devices create a stats 167 | // calculator to monitor datapath statistics. 168 | OFSwitch13DeviceContainer::Iterator it; 169 | for (it = m_openFlowDevs.Begin(); it != m_openFlowDevs.End(); it++) 170 | { 171 | Ptr dev = *it; 172 | std::string filename = prefix; 173 | std::string nodename; 174 | 175 | if (useNodeNames) 176 | { 177 | Ptr node = dev->GetObject(); 178 | nodename = Names::FindName(node); 179 | } 180 | if (nodename.size()) 181 | { 182 | filename += nodename; 183 | } 184 | else 185 | { 186 | filename += std::to_string(dev->GetDatapathId()); 187 | } 188 | filename += extension; 189 | 190 | statsFactory.Set("OutputFilename", StringValue(filename)); 191 | statsCalculator = statsFactory.Create(); 192 | statsCalculator->AggregateObject(dev); 193 | statsCalculator->HookSinks(dev); 194 | } 195 | } 196 | 197 | Ptr 198 | OFSwitch13Helper::InstallSwitch(Ptr swNode, NetDeviceContainer& swPorts) 199 | { 200 | NS_LOG_FUNCTION(this << swNode); 201 | 202 | // Install the OpenFlow device into switch node. 203 | Ptr openFlowDev = InstallSwitch(swNode); 204 | 205 | // Add switch ports. 206 | NetDeviceContainer::Iterator it; 207 | for (it = swPorts.Begin(); it != swPorts.End(); it++) 208 | { 209 | NS_LOG_INFO(" Adding switch port " << *it); 210 | openFlowDev->AddSwitchPort(*it); 211 | } 212 | 213 | return openFlowDev; 214 | } 215 | 216 | Ptr 217 | OFSwitch13Helper::InstallSwitch(Ptr swNode) 218 | { 219 | NS_LOG_FUNCTION(this << swNode); 220 | 221 | NS_LOG_INFO("Installing OpenFlow device on node " << swNode->GetId()); 222 | NS_ABORT_MSG_IF(m_blocked, "OpenFlow channels already configured."); 223 | 224 | // Install the TCP/IP stack into switch node. 225 | if (!swNode->GetObject()) 226 | { 227 | m_internet.Install(swNode); 228 | } 229 | 230 | // Create and aggregate the OpenFlow device to the switch node. 231 | Ptr openFlowDev = m_devFactory.Create(); 232 | swNode->AggregateObject(openFlowDev); 233 | m_openFlowDevs.Add(openFlowDev); 234 | m_switchNodes.Add(swNode); 235 | 236 | return openFlowDev; 237 | } 238 | 239 | OFSwitch13DeviceContainer 240 | OFSwitch13Helper::InstallSwitch(NodeContainer& swNodes) 241 | { 242 | NS_LOG_FUNCTION(this); 243 | 244 | // Iterate over the container and add OpenFlow devices to switch nodes. 245 | OFSwitch13DeviceContainer openFlowDevices; 246 | NodeContainer::Iterator it; 247 | for (it = swNodes.Begin(); it != swNodes.End(); it++) 248 | { 249 | openFlowDevices.Add(InstallSwitch(*it)); 250 | } 251 | 252 | return openFlowDevices; 253 | } 254 | 255 | void 256 | OFSwitch13Helper::SetAddressBase(Ipv4Address network, Ipv4Mask mask, Ipv4Address base) 257 | { 258 | NS_LOG_FUNCTION_NOARGS(); 259 | 260 | m_ipv4helper.SetBase(network, mask, base); 261 | } 262 | 263 | void 264 | OFSwitch13Helper::EnableDatapathLogs(std::string prefix, bool explicitFilename) 265 | { 266 | NS_LOG_FUNCTION_NOARGS(); 267 | 268 | // Saving library logs into output file. 269 | EnableBofussLog(true, prefix, explicitFilename); 270 | } 271 | 272 | void 273 | OFSwitch13Helper::DoDispose() 274 | { 275 | NS_LOG_FUNCTION(this); 276 | } 277 | 278 | } // namespace ns3 279 | #endif // NS3_OFSWITCH13 280 | -------------------------------------------------------------------------------- /helper/ofswitch13-internal-helper.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifdef NS3_OFSWITCH13 21 | 22 | #include "ofswitch13-internal-helper.h" 23 | 24 | #include 25 | #include 26 | 27 | namespace ns3 28 | { 29 | 30 | NS_LOG_COMPONENT_DEFINE("OFSwitch13InternalHelper"); 31 | NS_OBJECT_ENSURE_REGISTERED(OFSwitch13InternalHelper); 32 | 33 | class OFSwitch13Controller; 34 | 35 | OFSwitch13InternalHelper::OFSwitch13InternalHelper() 36 | { 37 | NS_LOG_FUNCTION(this); 38 | } 39 | 40 | OFSwitch13InternalHelper::~OFSwitch13InternalHelper() 41 | { 42 | NS_LOG_FUNCTION(this); 43 | } 44 | 45 | TypeId 46 | OFSwitch13InternalHelper::GetTypeId() 47 | { 48 | static TypeId tid = TypeId("ns3::OFSwitch13InternalHelper") 49 | .SetParent() 50 | .SetGroupName("OFSwitch13") 51 | .AddConstructor(); 52 | return tid; 53 | } 54 | 55 | void 56 | OFSwitch13InternalHelper::CreateOpenFlowChannels() 57 | { 58 | NS_LOG_FUNCTION(this); 59 | 60 | NS_LOG_INFO("Creating OpenFlow channels."); 61 | NS_ABORT_MSG_IF(m_blocked, "OpenFlow channels already configured."); 62 | 63 | // Block this helper to avoid further calls to install methods. 64 | m_blocked = true; 65 | 66 | // Enable checksum computations (mandatory for this module) 67 | GlobalValue::Bind("ChecksumEnabled", BooleanValue(true)); 68 | 69 | // Create and start the connections between switches and controllers. 70 | switch (m_channelType) 71 | { 72 | case OFSwitch13InternalHelper::SINGLE_CSMA: { 73 | NS_LOG_INFO("Attach all switches and controllers to the same CSMA network."); 74 | 75 | // Create the common channel for all switches and controllers. 76 | Ptr csmaChannel = 77 | CreateObjectWithAttributes("DataRate", DataRateValue(m_channelDataRate)); 78 | 79 | // Connecting all switches and controllers to the common channel. 80 | NetDeviceContainer switchDevices; 81 | Ipv4InterfaceContainer controllerAddrs; 82 | m_controlDevs = m_csmaHelper.Install(m_controlNodes, csmaChannel); 83 | switchDevices = m_csmaHelper.Install(m_switchNodes, csmaChannel); 84 | controllerAddrs = m_ipv4helper.Assign(m_controlDevs); 85 | m_ipv4helper.Assign(switchDevices); 86 | 87 | // Start the connections between controllers and switches. 88 | UintegerValue portValue; 89 | for (uint32_t ctIdx = 0; ctIdx < controllerAddrs.GetN(); ctIdx++) 90 | { 91 | m_controlApps.Get(ctIdx)->GetAttribute("Port", portValue); 92 | InetSocketAddress addr(controllerAddrs.GetAddress(ctIdx), portValue.Get()); 93 | 94 | OFSwitch13DeviceContainer::Iterator ofDev; 95 | for (ofDev = m_openFlowDevs.Begin(); ofDev != m_openFlowDevs.End(); ofDev++) 96 | { 97 | NS_LOG_INFO("Connect switch " << (*ofDev)->GetDatapathId() << " to controller " 98 | << addr.GetIpv4() << " port " << addr.GetPort()); 99 | Simulator::ScheduleNow(&OFSwitch13Device::StartControllerConnection, *ofDev, addr); 100 | } 101 | } 102 | m_ipv4helper.NewNetwork(); 103 | break; 104 | } 105 | case OFSwitch13InternalHelper::DEDICATED_CSMA: 106 | case OFSwitch13InternalHelper::DEDICATED_P2P: { 107 | // Setting channel/device data rates. 108 | m_p2pHelper.SetDeviceAttribute("DataRate", DataRateValue(m_channelDataRate)); 109 | m_csmaHelper.SetChannelAttribute("DataRate", DataRateValue(m_channelDataRate)); 110 | 111 | // To avoid IP datagram fragmentation, we are configuring the OpenFlow 112 | // channel devices with a very large MTU value. The TCP sockets used to 113 | // send packets to these devices are also configured to use a large 114 | // segment size at OFSwitch13Controller and OFSwitch13Device. 115 | m_csmaHelper.SetDeviceAttribute("Mtu", UintegerValue(9000)); 116 | m_p2pHelper.SetDeviceAttribute("Mtu", UintegerValue(9000)); 117 | 118 | // Using large queues on devices to avoid losing packets. 119 | m_csmaHelper.SetQueue("ns3::DropTailQueue", "MaxSize", StringValue("65536p")); 120 | m_p2pHelper.SetQueue("ns3::DropTailQueue", "MaxSize", StringValue("65536p")); 121 | 122 | // Create individual channels for each pair switch/controller. 123 | UintegerValue portValue; 124 | for (uint32_t swIdx = 0; swIdx < m_switchNodes.GetN(); swIdx++) 125 | { 126 | Ptr swNode = m_switchNodes.Get(swIdx); 127 | Ptr ofDev = m_openFlowDevs.Get(swIdx); 128 | 129 | for (uint32_t ctIdx = 0; ctIdx < m_controlNodes.GetN(); ctIdx++) 130 | { 131 | Ptr ctNode = m_controlNodes.Get(ctIdx); 132 | Ptr ctApp = m_controlApps.Get(ctIdx); 133 | 134 | NetDeviceContainer pairDevs = Connect(ctNode, swNode); 135 | m_controlDevs.Add(pairDevs.Get(0)); 136 | Ipv4InterfaceContainer pairIfaces = m_ipv4helper.Assign(pairDevs); 137 | 138 | // Start this single connection between switch and controller. 139 | m_controlApps.Get(ctIdx)->GetAttribute("Port", portValue); 140 | InetSocketAddress addr(pairIfaces.GetAddress(0), portValue.Get()); 141 | 142 | NS_LOG_INFO("Connect switch " << ofDev->GetDatapathId() << " to controller " 143 | << addr.GetIpv4() << " port " << addr.GetPort()); 144 | Simulator::ScheduleNow(&OFSwitch13Device::StartControllerConnection, ofDev, addr); 145 | m_ipv4helper.NewNetwork(); 146 | } 147 | } 148 | break; 149 | } 150 | default: { 151 | NS_ABORT_MSG("Invalid OpenflowChannelType."); 152 | } 153 | } 154 | } 155 | 156 | Ptr 157 | OFSwitch13InternalHelper::InstallController(Ptr cNode, Ptr controller) 158 | { 159 | NS_LOG_FUNCTION(this << cNode << controller); 160 | 161 | NS_LOG_INFO("Installing OpenFlow controller on node " << cNode->GetId()); 162 | NS_ABORT_MSG_IF(m_blocked, "OpenFlow channels already configured."); 163 | 164 | // Install the TCP/IP stack into controller node. 165 | if (!cNode->GetObject()) 166 | { 167 | m_internet.Install(cNode); 168 | } 169 | 170 | // Configure and save controller application and node. 171 | controller->SetStartTime(Seconds(0)); 172 | cNode->AddApplication(controller); 173 | m_controlApps.Add(controller); 174 | m_controlNodes.Add(cNode); 175 | 176 | return controller; 177 | } 178 | 179 | void 180 | OFSwitch13InternalHelper::DoDispose() 181 | { 182 | NS_LOG_FUNCTION(this); 183 | 184 | OFSwitch13Helper::DoDispose(); 185 | } 186 | 187 | NetDeviceContainer 188 | OFSwitch13InternalHelper::Connect(Ptr ctrl, Ptr swtch) 189 | { 190 | NS_LOG_FUNCTION(this << ctrl << swtch); 191 | 192 | NodeContainer pairNodes(ctrl, swtch); 193 | switch (m_channelType) 194 | { 195 | case OFSwitch13InternalHelper::DEDICATED_CSMA: { 196 | return m_csmaHelper.Install(pairNodes); 197 | } 198 | case OFSwitch13InternalHelper::DEDICATED_P2P: { 199 | return m_p2pHelper.Install(pairNodes); 200 | } 201 | case OFSwitch13InternalHelper::SINGLE_CSMA: 202 | default: { 203 | NS_ABORT_MSG("Invalid OpenflowChannelType."); 204 | } 205 | } 206 | } 207 | 208 | } // namespace ns3 209 | #endif // NS3_OFSWITCH13 210 | -------------------------------------------------------------------------------- /helper/ofswitch13-internal-helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef OFSWITCH13_INTERNAL_HELPER_H 21 | #define OFSWITCH13_INTERNAL_HELPER_H 22 | 23 | #include 24 | 25 | namespace ns3 26 | { 27 | 28 | class Node; 29 | class AttributeValue; 30 | class OFSwitch13Controller; 31 | class OFSwitch13LearningController; 32 | 33 | /** 34 | * \ingroup ofswitch13 35 | * 36 | * This helper extends the base class and can be instantiated to create and 37 | * configure an OpenFlow 1.3 network domain composed of one or more OpenFlow 38 | * switches connected to a single or multiple internal simulated OpenFlow 39 | * controllers. It brings methods for installing the controller and creating 40 | * the OpenFlow channels. 41 | */ 42 | class OFSwitch13InternalHelper : public OFSwitch13Helper 43 | { 44 | public: 45 | OFSwitch13InternalHelper(); //!< Default constructor. 46 | ~OFSwitch13InternalHelper() override; //!< Dummy destructor, see DoDispose. 47 | 48 | /** 49 | * Register this type. 50 | * \return The object TypeId. 51 | */ 52 | static TypeId GetTypeId(); 53 | 54 | // Inherited from OFSwitch13Helper. 55 | void CreateOpenFlowChannels() override; 56 | 57 | /** 58 | * This method installs the given controller application into the given 59 | * controller node. If no application is given, a new (default) learning 60 | * controller application is created and installed into controller node. 61 | * \param cNode The node to configure as controller. 62 | * \param controller The controller application to install into cNode 63 | * \return The installed controller application. 64 | */ 65 | Ptr InstallController( 66 | Ptr cNode, 67 | Ptr controller = CreateObject()); 68 | 69 | protected: 70 | /** Destructor implementation. */ 71 | void DoDispose() override; 72 | 73 | /** 74 | * Create an individual connection between the switch and the controller 75 | * node, using the already configured channel type. 76 | * \param ctrl The controller node. 77 | * \param swtch The switch node. 78 | * \return The devices created on both nodes. 79 | */ 80 | NetDeviceContainer Connect(Ptr ctrl, Ptr swtch); 81 | 82 | ApplicationContainer m_controlApps; //!< OF controller apps. 83 | NodeContainer m_controlNodes; //!< OF controller nodes. 84 | }; 85 | 86 | } // namespace ns3 87 | #endif /* OFSWITCH13_INTERNAL_HELPER_H */ 88 | -------------------------------------------------------------------------------- /helper/ofswitch13-stats-calculator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef OFSWITCH13_STATS_CALCULATOR_H 21 | #define OFSWITCH13_STATS_CALCULATOR_H 22 | 23 | #include 24 | 25 | namespace ns3 26 | { 27 | 28 | /** 29 | * \ingroup ofswitch13 30 | * \brief This class monitors a single OpenFlow switch device to collect 31 | * statistics and periodically write them to an output file. This stats 32 | * calculator connects to a collection of trace sources in the OpenFlow switch 33 | * device to monitor the following metrics: 34 | * 35 | * -# [LoaKbps] CPU processing load in the last interval (Kbps); 36 | * -# [LoaUsag] Average CPU processing capacity usage (percent); 37 | * -# [Packets] Packets processed by the pipeline in the last interval; 38 | * -# [DlyUsec] EWMA pipeline lookup delay for packet processing (usecs); 39 | * -# [LoaDrps] Packets dropped by capacity overloaded in the last interval; 40 | * -# [MetDrps] Packets dropped by meter bands in the last interval; 41 | * -# [TabDrps] Unmatched packets dropped by flow tables in the last interval; 42 | * -# [FloMods] Flow-mod operations executed in the last interval; 43 | * -# [MetMods] Meter-mod operations executed in the last interval; 44 | * -# [GroMods] Group-mod operations executed in the last interval; 45 | * -# [PktsIn] Packets-in sent to the controller in the last interval; 46 | * -# [PktsOut] Packets-out received from the controller in the last interval; 47 | * -# [FloEntr] EWMA sum of entries in all pipeline flow tables; 48 | * -# [FloUsag] Average flow table usage, considering the sum of entries in 49 | * all flow tables divided by the aggregated sizes of all flow tables with 50 | * at least one flow entry installed (percent); 51 | * -# [MetEntr] EWMA number of entries in meter table; 52 | * -# [MetUsag] Average meter table usage (percent); 53 | * -# [GroEntr] EWMA number of entries in group table; 54 | * -# [GroUsag] Average group table usage (percent); 55 | * -# [BufPkts] EWMA number of packets in switch buffer; 56 | * -# [BufUsag] Average switch buffer usage (percent); 57 | * 58 | * When the FlowTableDetails attribute is set to 'true', the EWMA number of 59 | * entries and the average flow table usage for each pipeline flow table is 60 | * also available under the columns ``T**Entr`` and ``T**Usag``. 61 | */ 62 | class OFSwitch13StatsCalculator : public Object 63 | { 64 | public: 65 | OFSwitch13StatsCalculator(); //!< Default constructor. 66 | ~OFSwitch13StatsCalculator() override; //!< Default destructor. 67 | 68 | /** 69 | * Register this type. 70 | * \return The object TypeId. 71 | */ 72 | static TypeId GetTypeId(); 73 | 74 | /** 75 | * Hook switch device trace sources to stats calculator trace sinks. 76 | * \param device The OpenFlow switch device to monitor. 77 | */ 78 | void HookSinks(Ptr device); 79 | 80 | /** 81 | * \name EWMA statistics calculators. 82 | * Get the average metric values that are updated at every datapath timeout 83 | * operation using an Exponentially Weighted Moving Average. 84 | * \param tableId The pipeline table ID. 85 | * \return The requested metric value. 86 | */ 87 | //\{ 88 | uint32_t GetEwmaBufferEntries() const; 89 | DataRate GetEwmaCpuLoad() const; 90 | uint32_t GetEwmaFlowTableEntries(uint8_t tableId) const; 91 | uint32_t GetEwmaGroupTableEntries() const; 92 | uint32_t GetEwmaMeterTableEntries() const; 93 | Time GetEwmaPipelineDelay() const; 94 | uint32_t GetEwmaSumFlowEntries() const; 95 | //\} 96 | 97 | /** 98 | * \name Datapath usage statistics. 99 | * Get the usage statistics for datapath resources considering the EWMA 100 | * values and resources size. For the flow table usage, only those tables 101 | * with active flow entries are considered when calculating the average 102 | * usage value. 103 | * \param tableId The pipeline table ID. 104 | * \return The requested metric value. 105 | */ 106 | //\{ 107 | uint32_t GetAvgBufferUsage() const; 108 | uint32_t GetAvgCpuUsage() const; 109 | uint32_t GetAvgFlowTableUsage(uint8_t tableId) const; 110 | uint32_t GetAvgGroupTableUsage() const; 111 | uint32_t GetAvgMeterTableUsage() const; 112 | uint32_t GetAvgActFlowTableUsage() const; 113 | //\} 114 | 115 | protected: 116 | /** Destructor implementation. */ 117 | void DoDispose() override; 118 | 119 | // Inherited from ObjectBase. 120 | void NotifyConstructionCompleted() override; 121 | 122 | private: 123 | /** 124 | * Notify when a datapath timeout operation is completed. 125 | * \param device The OpenFlow device pointer. 126 | */ 127 | void NotifyDatapathTimeout(Ptr device); 128 | 129 | /** 130 | * Notify when a packet is dropped due to pipeline load. 131 | * \param packet The packet. 132 | */ 133 | void NotifyOverloadDrop(Ptr packet); 134 | 135 | /** 136 | * Notify when a packet is dropped by a meter band. 137 | * \param packet The packet. 138 | * \param meterId The meter ID. 139 | */ 140 | void NotifyMeterDrop(Ptr packet, uint32_t meterId); 141 | 142 | /** 143 | * Notify when an unmatched packet is dropped by a flow table without a 144 | * table-miss entry. 145 | * \param packet The packet. 146 | * \param tableId The flow table ID. 147 | */ 148 | void NotifyTableDrop(Ptr packet, uint8_t tableId); 149 | 150 | /** 151 | * Notify when a packet is sent to pipeline. 152 | * \param packet The packet. 153 | */ 154 | void NotifyPipelinePacket(Ptr packet); 155 | 156 | /** 157 | * Read statistics from switch, update internal counters, and dump data into 158 | * output file. 159 | */ 160 | void DumpStatistics(); 161 | 162 | Ptr m_device; //!< OpenFlow switch device. 163 | Ptr m_wrapper; //!< Output file wrapper. 164 | std::string m_filename; //!< Output file name. 165 | Time m_timeout; //!< Update timeout. 166 | Time m_lastUpdate; //!< Last update time. 167 | double m_alpha; //!< EWMA alpha parameter. 168 | bool m_details; //!< Pipeline table details. 169 | 170 | /** \name Internal counters, average values, and updated flags. */ 171 | //\{ 172 | double m_ewmaBufferEntries; 173 | double m_ewmaCpuLoad; 174 | double m_ewmaGroupEntries; 175 | double m_ewmaMeterEntries; 176 | double m_ewmaPipelineDelay; 177 | double m_ewmaSumFlowEntries; 178 | 179 | std::vector m_ewmaFlowEntries; 180 | 181 | uint64_t m_bytes; 182 | uint64_t m_lastFlowMods; 183 | uint64_t m_lastGroupMods; 184 | uint64_t m_lastMeterMods; 185 | uint64_t m_lastPacketsIn; 186 | uint64_t m_lastPacketsOut; 187 | uint64_t m_loadDrops; 188 | uint64_t m_meterDrops; 189 | uint64_t m_tableDrops; 190 | uint64_t m_packets; 191 | //\} 192 | }; 193 | 194 | } // namespace ns3 195 | #endif /* OFSWITCH13_STATS_CALCULATOR_H */ 196 | -------------------------------------------------------------------------------- /model/ofswitch13-interface.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #include "ofswitch13-interface.h" 21 | 22 | #include "ofswitch13-controller.h" 23 | #include "ofswitch13-device.h" 24 | 25 | namespace ns3 26 | { 27 | 28 | NS_LOG_COMPONENT_DEFINE("OFSwitch13Interface"); 29 | 30 | void 31 | EnableBofussLog(bool printToFile, 32 | std::string prefix, 33 | bool explicitFilename, 34 | std::string customLevels) 35 | { 36 | vlog_init(); 37 | vlog_set_pattern(VLF_ANY_FACILITY, "%d{%ss} [%c|%p] %m"); 38 | 39 | if (printToFile) 40 | { 41 | std::string filename = prefix; 42 | if (!explicitFilename) 43 | { 44 | if (!filename.empty() && filename.back() != '-') 45 | { 46 | filename += "-"; 47 | } 48 | filename += "BOFUSS.log"; 49 | } 50 | vlog_set_log_file(filename.c_str()); 51 | vlog_set_levels(VLM_ANY_MODULE, VLF_FILE, VLL_DBG); 52 | } 53 | else 54 | { 55 | vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_DBG); 56 | } 57 | 58 | if (!customLevels.empty()) 59 | { 60 | vlog_set_levels_from_string(customLevels.c_str()); 61 | } 62 | } 63 | 64 | struct ofpbuf* 65 | BufferFromPacket(Ptr packet, size_t bodyRoom, size_t headRoom) 66 | { 67 | NS_LOG_FUNCTION_NOARGS(); 68 | 69 | NS_ASSERT(packet->GetSize() <= bodyRoom); 70 | struct ofpbuf* buffer; 71 | uint32_t pktSize; 72 | 73 | pktSize = packet->GetSize(); 74 | buffer = ofpbuf_new_with_headroom(bodyRoom, headRoom); 75 | packet->CopyData((uint8_t*)ofpbuf_put_uninit(buffer, pktSize), pktSize); 76 | return buffer; 77 | } 78 | 79 | Ptr 80 | PacketFromMsg(struct ofl_msg_header* msg, uint32_t xid) 81 | { 82 | NS_LOG_FUNCTION_NOARGS(); 83 | 84 | int error; 85 | uint8_t* buf; 86 | size_t buf_size; 87 | Ptr packet; 88 | struct ofpbuf* buffer; 89 | 90 | buffer = ofpbuf_new(0); 91 | error = ofl_msg_pack(msg, xid, &buf, &buf_size, nullptr); 92 | if (!error) 93 | { 94 | ofpbuf_use(buffer, buf, buf_size); 95 | ofpbuf_put_uninit(buffer, buf_size); 96 | packet = Create((uint8_t*)buffer->data, buffer->size); 97 | ofpbuf_delete(buffer); 98 | } 99 | return packet; 100 | } 101 | 102 | Ptr 103 | PacketFromBuffer(struct ofpbuf* buffer) 104 | { 105 | NS_LOG_FUNCTION_NOARGS(); 106 | 107 | return Create((uint8_t*)buffer->data, buffer->size); 108 | } 109 | 110 | } // namespace ns3 111 | 112 | using namespace ns3; 113 | 114 | /** 115 | * Overriding BOFUSS time_now weak function from timeval.c. 116 | * \return The current simulation time, in seconds. 117 | */ 118 | time_t 119 | time_now(void) 120 | { 121 | return static_cast(Simulator::Now().ToInteger(Time::S)); 122 | } 123 | 124 | /** 125 | * Overriding BOFUSS time_msec weak function from timeval.c. 126 | * \return The current simulation time, in milliseconds. 127 | */ 128 | long long int 129 | time_msec(void) 130 | { 131 | return static_cast(Simulator::Now().GetMilliSeconds()); 132 | } 133 | 134 | /** Overriding BOFUSS weak functions using static member functions. */ 135 | void 136 | send_packet_to_controller(struct pipeline* pl, struct packet* pkt, uint8_t table_id, uint8_t reason) 137 | { 138 | return OFSwitch13Device::SendPacketToController(pl, pkt, table_id, reason); 139 | } 140 | 141 | int 142 | send_openflow_buffer_to_remote(struct ofpbuf* buffer, struct remote* remote) 143 | { 144 | return OFSwitch13Device::SendOpenflowBufferToRemote(buffer, remote); 145 | } 146 | 147 | void 148 | dp_actions_output_port(struct packet* pkt, 149 | uint32_t out_port, 150 | uint32_t out_queue, 151 | uint16_t max_len, 152 | uint64_t cookie) 153 | { 154 | OFSwitch13Device::DpActionsOutputPort(pkt, out_port, out_queue, max_len, cookie); 155 | } 156 | 157 | void 158 | dpctl_send_and_print(struct vconn* vconn, struct ofl_msg_header* msg) 159 | { 160 | OFSwitch13Controller::DpctlSendAndPrint(vconn, msg); 161 | } 162 | 163 | void 164 | dpctl_transact_and_print(struct vconn* vconn, 165 | struct ofl_msg_header* req, 166 | struct ofl_msg_header** repl) 167 | { 168 | // Different from BOFUSS dpctl, this transaction doesn't wait for a reply, 169 | // as ns-3 socket library doesn't provide blocking sockets. So, we send the 170 | // request and return. The reply will came later, using the ns-3 callback 171 | // mechanism. 172 | OFSwitch13Controller::DpctlSendAndPrint(vconn, req); 173 | } 174 | -------------------------------------------------------------------------------- /model/ofswitch13-interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | /** 21 | * \defgroup ofswitch13 OpenFlow 1.3 software switch 22 | * 23 | * This section documents the API of the ns-3 OpenFlow 1.3 compatible switch 24 | * and controller interface. It follows the OpenFlow 1.3 switch specification 25 | * . 26 | * It depends on the CPqD BOFUSS software switch available at 27 | * , compiled as a library. 28 | * Check the manual for tutorials on how to compile and use this module. 29 | */ 30 | #ifndef OFSWITCH13_INTERFACE_H 31 | #define OFSWITCH13_INTERFACE_H 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | extern "C" 40 | { 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | } 69 | 70 | namespace ns3 71 | { 72 | 73 | /** 74 | * TracedCallback signature for sending packets from CsmaNetDevice to OpenFlow 75 | * pipeline. 76 | * \attention The packet can be modified by the OpenFlow pipeline. 77 | * \param netdev The underlying CsmaNetDevice switch port. 78 | * \param packet The packet. 79 | */ 80 | typedef void (*OpenFlowCallback)(Ptr packet); 81 | 82 | /** 83 | * \ingroup ofswitch13 84 | * Enable the logging system of the BOFUSS library. By default, it will 85 | * configure de logging system for maximum verbose dump on console. You can set 86 | * the \p printToFile parameter to dump messages to file instead. 87 | * \param printToFile Dump log messages to file instead of console. 88 | * \param prefix Filename prefix to use for log files. 89 | * \param explicitFilename Treat the prefix as an explicit filename if true. 90 | * \param customLevels Custom vlog levels mod1[:facility[:level]] mod2[... 91 | */ 92 | void EnableBofussLog(bool printToFile = false, 93 | std::string prefix = "", 94 | bool explicitFilename = false, 95 | std::string customLevels = ""); 96 | 97 | /** 98 | * \ingroup ofswitch13 99 | * Create an internal BOFUSS buffer from ns3::Packet. Takes a Ptr and 100 | * generates a buffer (struct ofpbuf*) from it, loading the packet data as well 101 | * as its headers into the buffer. 102 | * \param packet The ns-3 packet. 103 | * \param bodyRoom The size to allocate for data. 104 | * \param headRoom The size to allocate for headers (left uninitialized). 105 | * \return The OpenFlow Buffer created from the packet. 106 | */ 107 | struct ofpbuf* BufferFromPacket(Ptr packet, size_t bodyRoom, size_t headRoom = 0); 108 | 109 | /** 110 | * \ingroup ofswitch13 111 | * Create a new ns3::Packet from internal OFLib message. Takes a ofl_msg_* 112 | * structure, pack the message using wire format and generates a Ptr 113 | * from it. 114 | * \param msg The OFLib message structure. 115 | * \param xid The transaction id to use. 116 | * \return The ns3::Packet created. 117 | */ 118 | Ptr PacketFromMsg(struct ofl_msg_header* msg, uint32_t xid = 0); 119 | 120 | /** 121 | * \ingroup ofswitch13 122 | * Create a new ns3::Packet from internal BOFUSS buffer. Takes a buffer (struct 123 | * ofpbuf*) and generates a Ptr from it, load the data as well as its 124 | * headers into the packet. 125 | * \param buffer The internal buffer. 126 | * \return The ns3::Packet created. 127 | */ 128 | Ptr PacketFromBuffer(struct ofpbuf* buffer); 129 | 130 | } // namespace ns3 131 | #endif /* OFSWITCH13_INTERFACE_H */ 132 | -------------------------------------------------------------------------------- /model/ofswitch13-learning-controller.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifdef NS3_OFSWITCH13 21 | 22 | #include "ofswitch13-learning-controller.h" 23 | 24 | namespace ns3 25 | { 26 | 27 | NS_LOG_COMPONENT_DEFINE("OFSwitch13LearningController"); 28 | NS_OBJECT_ENSURE_REGISTERED(OFSwitch13LearningController); 29 | 30 | /********** Public methods ***********/ 31 | OFSwitch13LearningController::OFSwitch13LearningController() 32 | { 33 | NS_LOG_FUNCTION(this); 34 | } 35 | 36 | OFSwitch13LearningController::~OFSwitch13LearningController() 37 | { 38 | NS_LOG_FUNCTION(this); 39 | } 40 | 41 | TypeId 42 | OFSwitch13LearningController::GetTypeId() 43 | { 44 | static TypeId tid = TypeId("ns3::OFSwitch13LearningController") 45 | .SetParent() 46 | .SetGroupName("OFSwitch13") 47 | .AddConstructor(); 48 | return tid; 49 | } 50 | 51 | void 52 | OFSwitch13LearningController::DoDispose() 53 | { 54 | NS_LOG_FUNCTION(this); 55 | 56 | m_learnedInfo.clear(); 57 | OFSwitch13Controller::DoDispose(); 58 | } 59 | 60 | ofl_err 61 | OFSwitch13LearningController::HandlePacketIn(struct ofl_msg_packet_in* msg, 62 | Ptr swtch, 63 | uint32_t xid) 64 | { 65 | NS_LOG_FUNCTION(this << swtch << xid); 66 | 67 | static int prio = 100; 68 | uint32_t outPort = OFPP_FLOOD; 69 | enum ofp_packet_in_reason reason = msg->reason; 70 | 71 | // Get the switch datapath ID 72 | uint64_t swDpId = swtch->GetDpId(); 73 | 74 | char* msgStr = ofl_structs_match_to_string((struct ofl_match_header*)msg->match, nullptr); 75 | NS_LOG_DEBUG("Packet in match: " << msgStr); 76 | free(msgStr); 77 | 78 | if (reason == OFPR_NO_MATCH) 79 | { 80 | // Let's get necessary information (input port and mac address) 81 | uint32_t inPort; 82 | size_t portLen = OXM_LENGTH(OXM_OF_IN_PORT); // (Always 4 bytes) 83 | struct ofl_match_tlv* input = 84 | oxm_match_lookup(OXM_OF_IN_PORT, (struct ofl_match*)msg->match); 85 | memcpy(&inPort, input->value, portLen); 86 | 87 | Mac48Address src48; 88 | struct ofl_match_tlv* ethSrc = 89 | oxm_match_lookup(OXM_OF_ETH_SRC, (struct ofl_match*)msg->match); 90 | src48.CopyFrom(ethSrc->value); 91 | 92 | Mac48Address dst48; 93 | struct ofl_match_tlv* ethDst = 94 | oxm_match_lookup(OXM_OF_ETH_DST, (struct ofl_match*)msg->match); 95 | dst48.CopyFrom(ethDst->value); 96 | 97 | // Get L2Table for this datapath 98 | auto it = m_learnedInfo.find(swDpId); 99 | if (it != m_learnedInfo.end()) 100 | { 101 | L2Table_t* l2Table = &it->second; 102 | 103 | // Looking for out port based on dst address (except for broadcast) 104 | if (!dst48.IsBroadcast()) 105 | { 106 | auto itDst = l2Table->find(dst48); 107 | if (itDst != l2Table->end()) 108 | { 109 | outPort = itDst->second; 110 | } 111 | else 112 | { 113 | NS_LOG_DEBUG("No L2 info for mac " << dst48 << ". Flood."); 114 | } 115 | } 116 | 117 | // Learning port from source address 118 | NS_ASSERT_MSG(!src48.IsBroadcast(), "Invalid src broadcast addr"); 119 | auto itSrc = l2Table->find(src48); 120 | if (itSrc == l2Table->end()) 121 | { 122 | std::pair entry(src48, inPort); 123 | auto ret = l2Table->insert(entry); 124 | if (ret.second == false) 125 | { 126 | NS_LOG_ERROR("Can't insert mac48address / port pair"); 127 | } 128 | else 129 | { 130 | NS_LOG_DEBUG("Learning mac " << src48 << " at port " << inPort); 131 | 132 | // Send a flow-mod to switch creating this flow. Let's 133 | // configure the flow entry to 10s idle timeout and to 134 | // notify the controller when flow expires. (flags=0x0001) 135 | 136 | // clang-format off 137 | std::ostringstream cmd; 138 | cmd << "flow-mod cmd=add,table=0,idle=10,flags=0x0001" 139 | << ",prio=" << ++prio 140 | << " eth_dst=" << src48 141 | << " apply:output=" << inPort; 142 | // clang-format on 143 | DpctlExecute(swDpId, cmd.str()); 144 | } 145 | } 146 | else 147 | { 148 | NS_ASSERT_MSG(itSrc->second == inPort, "Inconsistent L2 switching table"); 149 | } 150 | } 151 | else 152 | { 153 | NS_LOG_ERROR("No L2 table for this datapath id " << swDpId); 154 | } 155 | 156 | // Lets send the packet out to switch. 157 | struct ofl_msg_packet_out reply; 158 | reply.header.type = OFPT_PACKET_OUT; 159 | reply.buffer_id = msg->buffer_id; 160 | reply.in_port = inPort; 161 | reply.data_length = 0; 162 | reply.data = nullptr; 163 | 164 | if (msg->buffer_id == NO_BUFFER) 165 | { 166 | // No packet buffer. Send data back to switch 167 | reply.data_length = msg->data_length; 168 | reply.data = msg->data; 169 | } 170 | 171 | // Create output action 172 | auto a = (struct ofl_action_output*)xmalloc(sizeof(struct ofl_action_output)); 173 | a->header.type = OFPAT_OUTPUT; 174 | a->port = outPort; 175 | a->max_len = 0; 176 | 177 | reply.actions_num = 1; 178 | reply.actions = (struct ofl_action_header**)&a; 179 | 180 | SendToSwitch(swtch, (struct ofl_msg_header*)&reply, xid); 181 | free(a); 182 | } 183 | else 184 | { 185 | NS_LOG_WARN("This controller can't handle the packet. Unknown reason."); 186 | } 187 | 188 | // All handlers must free the message when everything is ok 189 | ofl_msg_free((struct ofl_msg_header*)msg, nullptr); 190 | return 0; 191 | } 192 | 193 | ofl_err 194 | OFSwitch13LearningController::HandleFlowRemoved(struct ofl_msg_flow_removed* msg, 195 | Ptr swtch, 196 | uint32_t xid) 197 | { 198 | NS_LOG_FUNCTION(this << swtch << xid); 199 | 200 | // Get the switch datapath ID 201 | uint64_t swDpId = swtch->GetDpId(); 202 | 203 | NS_LOG_DEBUG("Flow entry expired. Removing from L2 switch table."); 204 | auto it = m_learnedInfo.find(swDpId); 205 | if (it != m_learnedInfo.end()) 206 | { 207 | Mac48Address mac48; 208 | struct ofl_match_tlv* ethSrc = 209 | oxm_match_lookup(OXM_OF_ETH_DST, (struct ofl_match*)msg->stats->match); 210 | mac48.CopyFrom(ethSrc->value); 211 | 212 | L2Table_t* l2Table = &it->second; 213 | auto itSrc = l2Table->find(mac48); 214 | if (itSrc != l2Table->end()) 215 | { 216 | l2Table->erase(itSrc); 217 | } 218 | } 219 | 220 | // All handlers must free the message when everything is ok 221 | ofl_msg_free_flow_removed(msg, true, nullptr); 222 | return 0; 223 | } 224 | 225 | /********** Private methods **********/ 226 | void 227 | OFSwitch13LearningController::HandshakeSuccessful(Ptr swtch) 228 | { 229 | NS_LOG_FUNCTION(this << swtch); 230 | 231 | // Get the switch datapath ID 232 | uint64_t swDpId = swtch->GetDpId(); 233 | 234 | // After a successful handshake, let's install the table-miss entry, setting 235 | // to 128 bytes the maximum amount of data from a packet that should be sent 236 | // to the controller. 237 | DpctlExecute(swDpId, "flow-mod cmd=add,table=0,prio=0 apply:output=ctrl:128"); 238 | 239 | // Configure te switch to buffer packets and send only the first 128 bytes 240 | // of each packet sent to the controller when not using an output action to 241 | // the OFPP_CONTROLLER logical port. 242 | DpctlExecute(swDpId, "set-config miss=128"); 243 | 244 | // Create an empty L2SwitchingTable and insert it into m_learnedInfo 245 | L2Table_t l2Table; 246 | std::pair entry(swDpId, l2Table); 247 | auto ret = m_learnedInfo.insert(entry); 248 | if (ret.second == false) 249 | { 250 | NS_LOG_ERROR("Table exists for this datapath."); 251 | } 252 | } 253 | 254 | } // namespace ns3 255 | #endif // NS3_OFSWITCH13 256 | -------------------------------------------------------------------------------- /model/ofswitch13-learning-controller.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef OFSWITCH13_LEARNING_CONTROLLER_H 21 | #define OFSWITCH13_LEARNING_CONTROLLER_H 22 | 23 | #include "ofswitch13-controller.h" 24 | 25 | namespace ns3 26 | { 27 | 28 | /** 29 | * \ingroup ofswitch13 30 | * \brief An Learning OpenFlow 1.3 controller (works as L2 switch) 31 | */ 32 | class OFSwitch13LearningController : public OFSwitch13Controller 33 | { 34 | public: 35 | OFSwitch13LearningController(); //!< Default constructor 36 | ~OFSwitch13LearningController() override; //!< Dummy destructor. 37 | 38 | /** 39 | * Register this type. 40 | * \return The object TypeId. 41 | */ 42 | static TypeId GetTypeId(); 43 | 44 | /** Destructor implementation */ 45 | void DoDispose() override; 46 | 47 | /** 48 | * Handle packet-in messages sent from switch to this controller. Look for 49 | * L2 switching information, update the structures and send a packet-out 50 | * back. 51 | * \param msg The packet-in message. 52 | * \param swtch The switch information. 53 | * \param xid Transaction id. 54 | * \return 0 if everything's ok, otherwise an error number. 55 | */ 56 | ofl_err HandlePacketIn(struct ofl_msg_packet_in* msg, 57 | Ptr swtch, 58 | uint32_t xid) override; 59 | 60 | /** 61 | * Handle flow removed messages sent from switch to this controller. Look 62 | * for L2 switching information and removes associated entry. 63 | * \param msg The flow removed message. 64 | * \param swtch The switch information. 65 | * \param xid Transaction id. 66 | * \return 0 if everything's ok, otherwise an error number. 67 | */ 68 | ofl_err HandleFlowRemoved(struct ofl_msg_flow_removed* msg, 69 | Ptr swtch, 70 | uint32_t xid) override; 71 | 72 | protected: 73 | // Inherited from OFSwitch13Controller 74 | void HandshakeSuccessful(Ptr swtch) override; 75 | 76 | private: 77 | /** Map saving */ 78 | typedef std::map IpMacMap_t; 79 | IpMacMap_t m_arpTable; //!< ARP resolution table. 80 | 81 | /** 82 | * \name L2 switching structures 83 | */ 84 | //\{ 85 | /** L2SwitchingTable: map MacAddress to port */ 86 | typedef std::map L2Table_t; 87 | 88 | /** Map datapathID to L2SwitchingTable */ 89 | typedef std::map DatapathMap_t; 90 | 91 | /** Switching information for every datapath */ 92 | DatapathMap_t m_learnedInfo; 93 | //\} 94 | }; 95 | 96 | } // namespace ns3 97 | #endif /* OFSWITCH13_LEARNING_CONTROLLER_H */ 98 | -------------------------------------------------------------------------------- /model/ofswitch13-port.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef OFSWITCH13_PORT_H 21 | #define OFSWITCH13_PORT_H 22 | 23 | #include "ofswitch13-interface.h" 24 | #include "ofswitch13-queue.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | namespace ns3 32 | { 33 | 34 | // The following explicit template instantiation declaration prevents modules 35 | // including this header file from implicitly instantiating Queue. 36 | extern template class Queue; 37 | 38 | class OFSwitch13Device; 39 | 40 | /** 41 | * \ingroup ofswitch13 42 | * 43 | * A OpenFlow switch port to interconnect the underlying NetDevice to the 44 | * OpenFlow device through the OpenFlow receive callback. This class handles the 45 | * BOFUSS internal sw_port structure. 46 | * \see BOFUSS udatapath/dp_ports.h 47 | * \attention Each underlying NetDevice used as port must only be assigned a MAC 48 | * Address. Adding an Ipv4/IPv6 layer to it may cause error. 49 | */ 50 | class OFSwitch13Port : public Object 51 | { 52 | public: 53 | OFSwitch13Port(); //!< Default constructor 54 | ~OFSwitch13Port() override; //!< Dummy destructor, see DoDispose 55 | 56 | /** 57 | * Complete Constructor. Create and populate a new datapath port, notifying 58 | * the controller of this new port. 59 | * \see BOFUSS new_port() at udatapath/dp_ports.c 60 | * \param dp The datapath. 61 | * \param netDev The underlying NetDevice. 62 | * \param openflowDev The OpenFlow device. 63 | */ 64 | OFSwitch13Port(struct datapath* dp, Ptr netDev, Ptr openflowDev); 65 | 66 | /** 67 | * Register this type. 68 | * \return The object TypeId. 69 | */ 70 | static TypeId GetTypeId(); 71 | 72 | /** 73 | * Get the NetDevice pointer from the underlying port. 74 | * \return A pointer to the corresponding underlying NetDevice. 75 | */ 76 | Ptr GetPortDevice() const; 77 | 78 | /** 79 | * Get the OpenFlow port number for this port. 80 | * \return The port number. 81 | */ 82 | uint32_t GetPortNo() const; 83 | 84 | /** 85 | * Get the OpenFlow queue for this port. 86 | * \return The port queue. 87 | */ 88 | Ptr GetPortQueue() const; 89 | 90 | /** 91 | * Get a pointer to the internal BOFUSS port structure. 92 | * \return The requested pointer. 93 | */ 94 | struct sw_port* GetPortStruct(); 95 | 96 | /** 97 | * Get the OFSwitch13Device pointer from this port. 98 | * \return A pointer to the corresponding OFSwitch13Device. 99 | */ 100 | Ptr GetSwitchDevice() const; 101 | 102 | /** 103 | * Update the port state field based on NetDevice status, and notify the 104 | * controller when changes occurs. 105 | * \return true if the state of the port has changed, false otherwise. 106 | */ 107 | bool PortUpdateState(); 108 | 109 | /** 110 | * Send a packet over this OpenFlow switch port. It will check port 111 | * configuration, update counters and send the packet to the underlying 112 | * device. 113 | * \see BOFUSS function dp_ports_run() at udatapath/dp_ports.c 114 | * \param packet The Packet to send. 115 | * \param queueNo The queue to use. 116 | * \param tunnelId The metadata associated with a logical port. 117 | * \return true if the packet was sent successfully, false otherwise. 118 | */ 119 | bool Send(Ptr packet, uint32_t queueNo = 0, uint64_t tunnelId = 0); 120 | 121 | protected: 122 | /** Destructor implementation */ 123 | void DoDispose() override; 124 | 125 | // Inherited from ObjectBase. 126 | void NotifyConstructionCompleted() override; 127 | 128 | private: 129 | /** 130 | * Create the bitmaps of OFPPF_* describing port features. 131 | * \see BOFUSS netdev_get_features() at lib/netdev.c 132 | * \return Port features bitmap. 133 | */ 134 | uint32_t GetPortFeatures(); 135 | 136 | /** 137 | * Called when a packet is received on this OpenFlow switch port by the 138 | * underlying NetDevice. It will check port configuration, update counter 139 | * and send the packet to the OpenFlow pipeline. 140 | * \see BOFUSS function dp_ports_run() at udatapath/dp_ports.c 141 | * \param device Underlying ns-3 network device. 142 | * \param packet The received packet. 143 | * \param protocol Next protocol header value. 144 | * \param from Address of the correspondent. 145 | * \param to Address of the destination. 146 | * \param packetType Type of the packet. 147 | * \return true. 148 | */ 149 | bool Receive(Ptr device, 150 | Ptr packet, 151 | uint16_t protocol, 152 | const Address& from, 153 | const Address& to, 154 | NetDevice::PacketType packetType); 155 | 156 | /** Trace source fired when a packet arrives at this switch port. */ 157 | TracedCallback> m_rxTrace; 158 | 159 | /** Trace source fired when a packet will be sent over this switch port. */ 160 | TracedCallback> m_txTrace; 161 | 162 | uint64_t m_dpId; //!< OpenFlow datapath ID. 163 | uint32_t m_portNo; //!< Port number. 164 | struct sw_port* m_swPort; //!< BOFUSS port structure. 165 | Ptr m_netDev; //!< Underlying NetDevice. 166 | Ptr m_portQueue; //!< OpenFlow port Queue. 167 | ObjectFactory m_factQueue; //!< Factory for port queue. 168 | Ptr m_openflowDev; //!< OpenFlow device. 169 | }; 170 | 171 | } // namespace ns3 172 | #endif /* OFSWITCH13_PORT_H */ 173 | -------------------------------------------------------------------------------- /model/ofswitch13-priority-queue.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #include "ofswitch13-priority-queue.h" 21 | 22 | #include "ns3/log.h" 23 | #include "ns3/string.h" 24 | 25 | #undef NS_LOG_APPEND_CONTEXT 26 | #define NS_LOG_APPEND_CONTEXT std::clog << "[dp " << m_dpId << " port " << m_portNo << "] "; 27 | 28 | namespace ns3 29 | { 30 | 31 | NS_LOG_COMPONENT_DEFINE("OFSwitch13PriorityQueue"); 32 | NS_OBJECT_ENSURE_REGISTERED(OFSwitch13PriorityQueue); 33 | 34 | static ObjectFactory 35 | GetDefaultQueueFactory() 36 | { 37 | // Setting default internal queue configuration. 38 | ObjectFactory queueFactory; 39 | queueFactory.SetTypeId("ns3::DropTailQueue"); 40 | return queueFactory; 41 | } 42 | 43 | TypeId 44 | OFSwitch13PriorityQueue::GetTypeId() 45 | { 46 | static TypeId tid = 47 | TypeId("ns3::OFSwitch13PriorityQueue") 48 | .SetParent() 49 | .SetGroupName("OFSwitch13") 50 | .AddConstructor() 51 | .AddAttribute("NumQueues", 52 | "The number of internal priority queues.", 53 | TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, 54 | UintegerValue(1), 55 | MakeUintegerAccessor(&OFSwitch13PriorityQueue::m_numQueues), 56 | MakeUintegerChecker(1, PORT_MAX_QUEUES)) 57 | .AddAttribute("QueueFactory", 58 | "The object factory for internal priority queues.", 59 | TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, 60 | ObjectFactoryValue(GetDefaultQueueFactory()), 61 | MakeObjectFactoryAccessor(&OFSwitch13PriorityQueue::m_facQueues), 62 | MakeObjectFactoryChecker()); 63 | return tid; 64 | } 65 | 66 | OFSwitch13PriorityQueue::OFSwitch13PriorityQueue() 67 | : OFSwitch13Queue(), 68 | NS_LOG_TEMPLATE_DEFINE("OFSwitch13PriorityQueue") 69 | { 70 | NS_LOG_FUNCTION(this); 71 | } 72 | 73 | OFSwitch13PriorityQueue::~OFSwitch13PriorityQueue() 74 | { 75 | NS_LOG_FUNCTION(this); 76 | } 77 | 78 | Ptr 79 | OFSwitch13PriorityQueue::Dequeue() 80 | { 81 | NS_LOG_FUNCTION(this); 82 | 83 | int queueId = GetNonEmptyQueue(); 84 | if (queueId >= 0) 85 | { 86 | NS_LOG_DEBUG("Packet to be dequeued from queue " << queueId); 87 | Ptr packet = GetQueue(queueId)->Dequeue(); 88 | NotifyDequeue(packet); 89 | return packet; 90 | } 91 | 92 | NS_LOG_DEBUG("Queue empty"); 93 | return nullptr; 94 | } 95 | 96 | Ptr 97 | OFSwitch13PriorityQueue::Remove() 98 | { 99 | NS_LOG_FUNCTION(this); 100 | 101 | int queueId = GetNonEmptyQueue(); 102 | if (queueId >= 0) 103 | { 104 | NS_LOG_DEBUG("Packet to be removed from queue " << queueId); 105 | Ptr packet = GetQueue(queueId)->Remove(); 106 | NotifyRemove(packet); 107 | return packet; 108 | } 109 | 110 | NS_LOG_DEBUG("Queue empty"); 111 | return nullptr; 112 | } 113 | 114 | Ptr 115 | OFSwitch13PriorityQueue::Peek() const 116 | { 117 | NS_LOG_FUNCTION(this); 118 | 119 | int queueId = GetNonEmptyQueue(); 120 | if (queueId >= 0) 121 | { 122 | NS_LOG_DEBUG("Packet to be peeked from queue " << queueId); 123 | return GetQueue(queueId)->Peek(); 124 | } 125 | 126 | NS_LOG_DEBUG("Queue empty"); 127 | return nullptr; 128 | } 129 | 130 | void 131 | OFSwitch13PriorityQueue::DoInitialize() 132 | { 133 | NS_LOG_FUNCTION(this); 134 | 135 | // Creating the internal priority queues. 136 | for (int queueId = 0; queueId < m_numQueues; queueId++) 137 | { 138 | AddQueue(m_facQueues.Create>()); 139 | } 140 | 141 | // Chain up. 142 | OFSwitch13Queue::DoInitialize(); 143 | } 144 | 145 | int 146 | OFSwitch13PriorityQueue::GetNonEmptyQueue() const 147 | { 148 | NS_LOG_FUNCTION(this); 149 | 150 | for (int queueId = 0; queueId < GetNQueues(); queueId++) 151 | { 152 | if (GetQueue(queueId)->IsEmpty() == false) 153 | { 154 | return queueId; 155 | } 156 | } 157 | 158 | NS_LOG_DEBUG("All internal queues are empty."); 159 | return -1; 160 | } 161 | 162 | } // namespace ns3 163 | -------------------------------------------------------------------------------- /model/ofswitch13-priority-queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | #ifndef OFSWITCH13_PRIORITY_QUEUE_H 20 | #define OFSWITCH13_PRIORITY_QUEUE_H 21 | 22 | #include "ofswitch13-queue.h" 23 | 24 | namespace ns3 25 | { 26 | 27 | // The following explicit template instantiation declaration prevents modules 28 | // including this header file from implicitly instantiating Queue. 29 | extern template class Queue; 30 | 31 | /** 32 | * \ingroup ofswitch13 33 | * 34 | * This class implements the priority queuing discipline for OpenFlow queue. It 35 | * creates a collection of N priority queues, identified by IDs ranging from 0 36 | * to N-1 with decreasing priority (queue ID 0 has the highest priority). The 37 | * output scheduling algorithm ensures that higher-priority queues are always 38 | * served first. 39 | */ 40 | class OFSwitch13PriorityQueue : public OFSwitch13Queue 41 | { 42 | public: 43 | /** 44 | * Register this type. 45 | * \return The object TypeId. 46 | */ 47 | static TypeId GetTypeId(); 48 | 49 | OFSwitch13PriorityQueue(); //!< Default constructor. 50 | ~OFSwitch13PriorityQueue() override; //!< Dummy destructor, see DoDispose. 51 | 52 | // Inherited from Queue. 53 | Ptr Dequeue() override; 54 | Ptr Remove() override; 55 | Ptr Peek() const override; 56 | 57 | protected: 58 | // Inherited from Object. 59 | void DoInitialize() override; 60 | 61 | private: 62 | /** 63 | * Identify the highest-priority non-empty queue. 64 | * \return The queue ID. 65 | */ 66 | int GetNonEmptyQueue() const; 67 | 68 | ObjectFactory m_facQueues; //!< Factory for internal queues. 69 | int m_numQueues; //!< Number of internal queues. 70 | 71 | NS_LOG_TEMPLATE_DECLARE; //!< Redefinition of the log component. 72 | }; 73 | 74 | } // namespace ns3 75 | #endif /* OFSWITCH13_PRIORITY_QUEUE_H */ 76 | -------------------------------------------------------------------------------- /model/ofswitch13-queue.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #include "ofswitch13-queue.h" 21 | 22 | #include "queue-tag.h" 23 | 24 | #include "ns3/log.h" 25 | #include "ns3/object-vector.h" 26 | #include "ns3/string.h" 27 | 28 | #undef NS_LOG_APPEND_CONTEXT 29 | #define NS_LOG_APPEND_CONTEXT std::clog << "[dp " << m_dpId << " port " << m_portNo << "] "; 30 | 31 | namespace ns3 32 | { 33 | 34 | NS_LOG_COMPONENT_DEFINE("OFSwitch13Queue"); 35 | NS_OBJECT_ENSURE_REGISTERED(OFSwitch13Queue); 36 | 37 | TypeId 38 | OFSwitch13Queue::GetTypeId() 39 | { 40 | static TypeId tid = TypeId("ns3::OFSwitch13Queue") 41 | .SetParent>() 42 | .SetGroupName("OFSwitch13") 43 | .AddAttribute("QueueList", 44 | "The list of internal queues.", 45 | ObjectVectorValue(), 46 | MakeObjectVectorAccessor(&OFSwitch13Queue::m_queues), 47 | MakeObjectVectorChecker>()); 48 | return tid; 49 | } 50 | 51 | OFSwitch13Queue::OFSwitch13Queue() 52 | : Queue(), 53 | m_dpId(0), 54 | m_portNo(0), 55 | m_swPort(nullptr), 56 | NS_LOG_TEMPLATE_DEFINE("OFSwitch13Queue") 57 | { 58 | NS_LOG_FUNCTION(this); 59 | } 60 | 61 | OFSwitch13Queue::~OFSwitch13Queue() 62 | { 63 | NS_LOG_FUNCTION(this); 64 | } 65 | 66 | bool 67 | OFSwitch13Queue::Enqueue(Ptr packet) 68 | { 69 | NS_LOG_FUNCTION(this << packet); 70 | 71 | QueueTag queueTag; 72 | packet->PeekPacketTag(queueTag); 73 | int queueId = static_cast(queueTag.GetQueueId()); 74 | NS_ASSERT_MSG(queueId < GetNQueues(), "Queue ID is out of range."); 75 | NS_LOG_DEBUG("Packet to be enqueued in queue " << queueId); 76 | 77 | struct sw_queue* swQueue; 78 | swQueue = dp_ports_lookup_queue(m_swPort, queueId); 79 | NS_ASSERT_MSG(swQueue, "Invalid queue id."); 80 | 81 | bool retval = GetQueue(queueId)->Enqueue(packet); 82 | if (retval) 83 | { 84 | swQueue->stats->tx_packets++; 85 | swQueue->stats->tx_bytes += packet->GetSize(); 86 | 87 | // Enqueue the packet in this queue too. This is necessary to ensure 88 | // consistent statistics. Otherwise, when the NetDevice calls the 89 | // IsEmpty() method, it will return true. 90 | DoEnqueue(GetContainer().end(), packet); 91 | } 92 | else 93 | { 94 | NS_LOG_DEBUG("Packet enqueue dropped by internal queue " << queueId); 95 | swQueue->stats->tx_errors++; 96 | 97 | // Drop the packet in this queue too. This is necessary to ensure 98 | // consistent statistics. 99 | DropBeforeEnqueue(packet); 100 | } 101 | return retval; 102 | } 103 | 104 | int 105 | OFSwitch13Queue::GetNQueues() const 106 | { 107 | return m_queues.size(); 108 | } 109 | 110 | Ptr> 111 | OFSwitch13Queue::GetQueue(int queueId) const 112 | { 113 | return m_queues.at(queueId); 114 | } 115 | 116 | void 117 | OFSwitch13Queue::SetPortStruct(struct sw_port* port) 118 | { 119 | NS_LOG_FUNCTION(this << port); 120 | 121 | m_swPort = port; 122 | m_dpId = port->dp->id; 123 | m_portNo = port->conf->port_no; 124 | } 125 | 126 | void 127 | OFSwitch13Queue::DoDispose() 128 | { 129 | NS_LOG_FUNCTION(this); 130 | 131 | // While m_swPort is valid, free internal stats and props structures for 132 | // each available queue 133 | if (m_swPort) 134 | { 135 | struct sw_queue* swQueue; 136 | for (int queueId = 0; queueId < GetNQueues(); queueId++) 137 | { 138 | swQueue = &(m_swPort->queues[queueId]); 139 | free(swQueue->stats); 140 | free(swQueue->props); 141 | } 142 | m_swPort = nullptr; 143 | } 144 | m_queues.clear(); 145 | 146 | // Chain up. 147 | Queue::DoDispose(); 148 | } 149 | 150 | void 151 | OFSwitch13Queue::DoInitialize() 152 | { 153 | NS_LOG_FUNCTION(this); 154 | 155 | // Chain up. 156 | Queue::DoInitialize(); 157 | } 158 | 159 | uint32_t 160 | OFSwitch13Queue::AddQueue(Ptr> queue) 161 | { 162 | NS_LOG_FUNCTION(this << queue); 163 | 164 | NS_ASSERT_MSG(queue, "Invalid queue pointer."); 165 | NS_ASSERT_MSG(m_swPort, "Invalid OpenFlow port metadata."); 166 | 167 | uint32_t queueId = (m_swPort->num_queues)++; 168 | struct sw_queue* swQueue = &(m_swPort->queues[queueId]); 169 | NS_ASSERT_MSG(!swQueue->port, "Queue id already in use."); 170 | 171 | // Filling BOFUSS internal structures for this queue 172 | swQueue->port = m_swPort; 173 | swQueue->created = time_msec(); 174 | 175 | size_t oflQueueStatsSize = sizeof(struct ofl_queue_stats); 176 | swQueue->stats = (struct ofl_queue_stats*)xmalloc(oflQueueStatsSize); 177 | memset(swQueue->stats, 0x00, oflQueueStatsSize); 178 | swQueue->stats->port_no = m_swPort->conf->port_no; 179 | swQueue->stats->queue_id = queueId; 180 | 181 | size_t oflPacketQueueSize = sizeof(struct ofl_packet_queue); 182 | swQueue->props = (struct ofl_packet_queue*)xmalloc(oflPacketQueueSize); 183 | swQueue->props->queue_id = queueId; 184 | swQueue->props->properties_num = 0; 185 | 186 | // Inserting the ns3::Queue object into queue list. 187 | m_queues.emplace_back(queue); 188 | NS_LOG_DEBUG("New queue with ID " << queueId); 189 | 190 | // Update the size of this queue. 191 | uint32_t maxSizeValue = 0; 192 | QueueSizeUnit maxSizeUnit = m_queues.at(0)->GetMaxSize().GetUnit(); 193 | for (const auto& queueIt : m_queues) 194 | { 195 | NS_ASSERT_MSG(queueIt->GetMaxSize().GetUnit() == maxSizeUnit, 196 | "Be consistent with queues operation modes."); 197 | maxSizeValue += queueIt->GetMaxSize().GetValue(); 198 | } 199 | SetMaxSize(QueueSize(maxSizeUnit, maxSizeValue)); 200 | 201 | return queueId; 202 | } 203 | 204 | void 205 | OFSwitch13Queue::NotifyDequeue(Ptr packet) 206 | { 207 | NS_LOG_FUNCTION(this << packet); 208 | 209 | // Dequeue the packet from this queue too. As we don't know the exactly 210 | // packet location on this queue, we have to look for it. 211 | for (auto it = GetContainer().begin(); it != GetContainer().end(); it++) 212 | { 213 | if ((*it) == packet) 214 | { 215 | DoDequeue(it); 216 | return; 217 | } 218 | } 219 | NS_LOG_WARN("Packet was not found on this queue."); 220 | } 221 | 222 | void 223 | OFSwitch13Queue::NotifyRemove(Ptr packet) 224 | { 225 | NS_LOG_FUNCTION(this << packet); 226 | 227 | // Remove the packet from this queue too. As we don't know the exactly 228 | // packet location on this queue, we have to look for it. 229 | for (auto it = GetContainer().begin(); it != GetContainer().end(); it++) 230 | { 231 | if ((*it) == packet) 232 | { 233 | DoRemove(it); 234 | return; 235 | } 236 | } 237 | NS_LOG_WARN("Packet was not found on this queue."); 238 | } 239 | 240 | } // namespace ns3 241 | -------------------------------------------------------------------------------- /model/ofswitch13-queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | #ifndef OFSWITCH13_QUEUE_H 20 | #define OFSWITCH13_QUEUE_H 21 | 22 | #include "ofswitch13-interface.h" 23 | 24 | #include 25 | #include 26 | 27 | namespace ns3 28 | { 29 | 30 | // The following explicit template instantiation declaration prevents modules 31 | // including this header file from implicitly instantiating Queue. 32 | extern template class Queue; 33 | 34 | /** 35 | * \ingroup ofswitch13 36 | * \brief The OpenFlow 1.3 queue interface. 37 | * 38 | * An OpenFlow switch provides limited Quality-of-Service support (QoS) through 39 | * a simple queuing mechanism. One (or more) queues can attach to a port and be 40 | * used to map flow entries on it. Flow entries mapped to a specific queue will 41 | * be treated according to that queue's configuration. Queue configuration takes 42 | * place outside the OpenFlow protocol. 43 | * 44 | * This class implements the queue interface, extending the ns3::Queue 45 | * class to allow compatibility with the CsmaNetDevice used by OFSwitch13Port. 46 | * Internally, it holds a collection of N (possibly different) queues, 47 | * identified by IDs ranging from 0 to N-1. The Enqueue() method uses the 48 | * ns3::QueueTag to identify which internal queue will hold the packet. 49 | * Subclasses can perform different output scheduling algorithms by implementing 50 | * the Dequeue(), Remove() and Peek() methods, always calling the 51 | * NotifyDequeue() and NotifyRemoved() methods from this base class to keep 52 | * consistency. 53 | */ 54 | class OFSwitch13Queue : public Queue 55 | { 56 | public: 57 | /** 58 | * Register this type. 59 | * \return The object TypeId. 60 | */ 61 | static TypeId GetTypeId(); 62 | 63 | OFSwitch13Queue(); //!< Default constructor. 64 | ~OFSwitch13Queue() override; //!< Dummy destructor, see DoDispose. 65 | 66 | // Inherited from Queue. 67 | bool Enqueue(Ptr packet) override; 68 | 69 | /** 70 | * Get the number of internal queues. 71 | * \return The number of internal queues. 72 | */ 73 | int GetNQueues() const; 74 | 75 | /** 76 | * Get a pointer to internal queue with specific id. 77 | * \param queueId The queue id. 78 | * \return The queue pointer. 79 | * \internal This function is marked as const to allow its usage inside 80 | * DoPeek() member function. 81 | */ 82 | Ptr> GetQueue(int queueId) const; 83 | 84 | /** 85 | * Set the pointer to the internal BOFUSS port structure. 86 | * \param port The port structure pointer. 87 | */ 88 | void SetPortStruct(struct sw_port* port); 89 | 90 | protected: 91 | /** Destructor implementation. */ 92 | void DoDispose() override; 93 | 94 | // Inherited from Object. 95 | void DoInitialize() override; 96 | 97 | /** 98 | * Add a new internal queue to this OpenFlow queue interface. 99 | * \param queue The queue pointer. 100 | * \return The ID for this new internal queue. 101 | */ 102 | uint32_t AddQueue(Ptr> queue); 103 | 104 | /** 105 | * Notify the parent class of a packet dequeued from any internal queue. 106 | * \param packet The packet. 107 | */ 108 | void NotifyDequeue(Ptr packet); 109 | 110 | /** 111 | * Notify the parent class of a packet removed from any internal queue. 112 | * \param packet The packet. 113 | */ 114 | void NotifyRemove(Ptr packet); 115 | 116 | // Values used for logging context. 117 | uint64_t m_dpId; //!< OpenFlow datapath ID. 118 | uint32_t m_portNo; //!< OpenFlow port number. 119 | 120 | private: 121 | /** Structure to save the list of internal queues in this interface. */ 122 | typedef std::vector> QueueList_t; 123 | 124 | struct sw_port* m_swPort; //!< BOFUSS port structure. 125 | QueueList_t m_queues; //!< List of internal queues. 126 | 127 | NS_LOG_TEMPLATE_DECLARE; //!< Redefinition of the log component. 128 | }; 129 | 130 | } // namespace ns3 131 | #endif /* OFSWITCH13_QUEUE_H */ 132 | -------------------------------------------------------------------------------- /model/ofswitch13-socket-handler.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #include "ofswitch13-socket-handler.h" 21 | 22 | namespace ns3 23 | { 24 | 25 | NS_LOG_COMPONENT_DEFINE("OFSwitch13SocketHandler"); 26 | NS_OBJECT_ENSURE_REGISTERED(OFSwitch13SocketHandler); 27 | 28 | TypeId 29 | OFSwitch13SocketHandler::GetTypeId() 30 | { 31 | // clang-format off 32 | static TypeId tid = TypeId("ns3::OFSwitch13SocketHandler") 33 | .SetParent() 34 | .SetGroupName("OFSwitch13"); 35 | return tid; 36 | // clang-format on 37 | } 38 | 39 | OFSwitch13SocketHandler::OFSwitch13SocketHandler(Ptr socket) 40 | : m_socket(socket), 41 | m_pendingPacket(nullptr), 42 | m_pendingBytes(0), 43 | m_txQueue() 44 | { 45 | NS_LOG_FUNCTION(this << socket); 46 | 47 | // Setup socket callbacks. 48 | socket->SetSendCallback(MakeCallback(&OFSwitch13SocketHandler::Send, this)); 49 | socket->SetRecvCallback(MakeCallback(&OFSwitch13SocketHandler::Recv, this)); 50 | } 51 | 52 | OFSwitch13SocketHandler::~OFSwitch13SocketHandler() 53 | { 54 | NS_LOG_FUNCTION(this); 55 | } 56 | 57 | void 58 | OFSwitch13SocketHandler::SetReceiveCallback(MessageCallback cb) 59 | { 60 | NS_LOG_FUNCTION(this); 61 | 62 | m_receivedMsg = cb; 63 | } 64 | 65 | int 66 | OFSwitch13SocketHandler::SendMessage(Ptr packet) 67 | { 68 | NS_LOG_FUNCTION(this << packet); 69 | 70 | // Insert this message into tx queue and try to forward it to the socket. 71 | m_txQueue.push(packet); 72 | Send(m_socket, m_socket->GetTxAvailable()); 73 | return 0; 74 | } 75 | 76 | void 77 | OFSwitch13SocketHandler::DoDispose() 78 | { 79 | NS_LOG_FUNCTION(this); 80 | 81 | m_socket = nullptr; 82 | m_pendingPacket = nullptr; 83 | } 84 | 85 | void 86 | OFSwitch13SocketHandler::Send(Ptr socket, uint32_t available) 87 | { 88 | NS_LOG_FUNCTION(this << socket << available); 89 | 90 | while (!m_txQueue.empty()) 91 | { 92 | // Get a reference for the next packet in the queue and check for 93 | // available space in socket tx buffer. 94 | Ptr packet = m_txQueue.front(); 95 | if (socket->GetTxAvailable() < packet->GetSize()) 96 | { 97 | NS_LOG_WARN("No space available to send message now."); 98 | return; 99 | } 100 | 101 | // Remove the packet from the queue and send it to the socket. 102 | m_txQueue.pop(); 103 | int retval = socket->Send(packet); 104 | if (retval == -1) 105 | { 106 | NS_LOG_ERROR("Error while sending OpenFlow message to socket. " 107 | << "Discarding. Socket error: " << socket->GetErrno()); 108 | } 109 | } 110 | } 111 | 112 | void 113 | OFSwitch13SocketHandler::Recv(Ptr socket) 114 | { 115 | NS_LOG_FUNCTION(this << socket); 116 | 117 | static const size_t ofpHeaderSize = sizeof(struct ofp_header); 118 | Address from; 119 | 120 | // Repeat the loop until socket buffer gets empty. 121 | while (socket->GetRxAvailable()) 122 | { 123 | // If we don't have pending bytes from an incomplete OpenFlow messages 124 | // it means that this is the start of a new message. 125 | if (!m_pendingBytes) 126 | { 127 | // At least 8 bytes from the OpenFlow header must be available. 128 | if (socket->GetRxAvailable() < 8) 129 | { 130 | return; // Wait for more bytes. 131 | } 132 | 133 | // Read the OpenFlow header and get the OpenFlow message size. 134 | struct ofp_header header; 135 | m_pendingPacket = socket->RecvFrom(ofpHeaderSize, 0, from); 136 | m_pendingPacket->CopyData((uint8_t*)&header, ofpHeaderSize); 137 | m_pendingBytes = ntohs(header.length) - ofpHeaderSize; 138 | } 139 | 140 | // If we have pending bytes from an incomplete OpenFlow message and we 141 | // also have bytes available to read at socket, let's read them now. 142 | uint32_t read = std::min(m_pendingBytes, socket->GetRxAvailable()); 143 | if (read) 144 | { 145 | m_pendingPacket->AddAtEnd(socket->RecvFrom(read, 0, from)); 146 | m_pendingBytes -= read; 147 | } 148 | 149 | // If we don't have pending bytes anymore it means that now we have a 150 | // complete OpenFlow message. 151 | if (!m_pendingBytes) 152 | { 153 | // Let's send the message to the registered callback. 154 | if (!m_receivedMsg.IsNull()) 155 | { 156 | m_receivedMsg(m_pendingPacket, from); 157 | } 158 | m_pendingPacket = nullptr; 159 | } 160 | } 161 | } 162 | 163 | } // namespace ns3 164 | -------------------------------------------------------------------------------- /model/ofswitch13-socket-handler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef OFSWITCH13_SOCKET_HANDLER_H 21 | #define OFSWITCH13_SOCKET_HANDLER_H 22 | 23 | #include "ofswitch13-interface.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | namespace ns3 33 | { 34 | 35 | /** 36 | * \ingroup ofswitch13 37 | * Class used to read/send single OpenFlow message from/to an open socket. The 38 | * TCP socket receive callback is connected to the Recv() method, which is 39 | * responsible for reading the correct number of bytes of a complete OpenFlow 40 | * message. When the OpenFlow message is completely received, it is sent to the 41 | * connected callback that was previously set using the SetReceiveCallback() 42 | * method. On the other direction, the TCP socket send callback is connected to 43 | * the Send() method that forwards OpenFlow message received by the 44 | * SendMessage() method to the open socket, respecting the original order of the 45 | * messages. 46 | */ 47 | class OFSwitch13SocketHandler : public Object 48 | { 49 | public: 50 | /** 51 | * Register this type. 52 | * \return The object TypeId. 53 | */ 54 | static TypeId GetTypeId(); 55 | 56 | /** 57 | * Complete constructor. 58 | * \param socket The socket pointer. 59 | */ 60 | OFSwitch13SocketHandler(Ptr socket); 61 | ~OFSwitch13SocketHandler() override; //!< Dummy destructor, see DoDispose. 62 | 63 | /** 64 | * \param packet The packet with the received OpenFlow message. 65 | * \param sender The address of the sender. 66 | */ 67 | typedef Callback, Address> MessageCallback; 68 | 69 | /** 70 | * Set the callback to invoke whenever an OpenFlow message has been received 71 | * at the associated socket. 72 | * \param cb The callback to invoke. 73 | */ 74 | void SetReceiveCallback(MessageCallback cb); 75 | 76 | /** 77 | * Send an OpenFlow message to the TCP socket. 78 | * \param packet The packet with the OpenFlow message. 79 | * \return 0 if everything's ok, otherwise an error number. 80 | */ 81 | int SendMessage(Ptr packet); 82 | 83 | protected: 84 | /** Destructor implementation */ 85 | void DoDispose() override; 86 | 87 | private: 88 | /** 89 | * Callback for bytes available in tx buffer. 90 | * \param socket The connected socket. 91 | * \param available The number of bytes available into tx buffer. 92 | */ 93 | void Send(Ptr socket, uint32_t available); 94 | 95 | /** 96 | * Callback for bytes available in rx buffer. 97 | * \param socket The connected socket. 98 | */ 99 | void Recv(Ptr socket); 100 | 101 | Ptr m_socket; //!< TCP socket. 102 | Ptr m_pendingPacket; //!< Buffer for receiving bytes. 103 | uint32_t m_pendingBytes; //!< Pending bytes for message. 104 | MessageCallback m_receivedMsg; //!< OpenFlow message callback. 105 | std::queue> m_txQueue; //!< TX queue. 106 | }; 107 | 108 | } // namespace ns3 109 | #endif /* OFSWITCH13_SOCKET_HANDLER_H */ 110 | -------------------------------------------------------------------------------- /model/queue-tag.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #include "queue-tag.h" 21 | 22 | #include 23 | 24 | namespace ns3 25 | { 26 | 27 | NS_LOG_COMPONENT_DEFINE("QueueTag"); 28 | NS_OBJECT_ENSURE_REGISTERED(QueueTag); 29 | 30 | QueueTag::QueueTag() 31 | : m_queueId(0) 32 | { 33 | } 34 | 35 | QueueTag::QueueTag(uint32_t id) 36 | : m_queueId(id) 37 | { 38 | } 39 | 40 | TypeId 41 | QueueTag::GetTypeId() 42 | { 43 | static TypeId tid = TypeId("ns3::QueueTag") 44 | .SetParent() 45 | .SetGroupName("OFSwitch13") 46 | .AddConstructor(); 47 | return tid; 48 | } 49 | 50 | TypeId 51 | QueueTag::GetInstanceTypeId() const 52 | { 53 | return GetTypeId(); 54 | } 55 | 56 | void 57 | QueueTag::SetQueueId(uint32_t id) 58 | { 59 | m_queueId = id; 60 | } 61 | 62 | uint32_t 63 | QueueTag::GetQueueId() const 64 | { 65 | return m_queueId; 66 | } 67 | 68 | uint32_t 69 | QueueTag::GetSerializedSize() const 70 | { 71 | return 4; 72 | } 73 | 74 | void 75 | QueueTag::Serialize(TagBuffer i) const 76 | { 77 | i.WriteU32(m_queueId); 78 | } 79 | 80 | void 81 | QueueTag::Deserialize(TagBuffer i) 82 | { 83 | m_queueId = i.ReadU32(); 84 | } 85 | 86 | void 87 | QueueTag::Print(std::ostream& os) const 88 | { 89 | os << " QueueTag id=" << m_queueId; 90 | } 91 | 92 | } // namespace ns3 93 | -------------------------------------------------------------------------------- /model/queue-tag.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef QUEUE_TAG_H 21 | #define QUEUE_TAG_H 22 | 23 | #include 24 | 25 | namespace ns3 26 | { 27 | 28 | class Tag; 29 | 30 | /** 31 | * \ingroup ofswitch13 32 | * Tag used to hold the queue id before enqueueing a packet into 33 | * OFSwitch13Queue. 34 | */ 35 | class QueueTag : public Tag 36 | { 37 | public: 38 | /** 39 | * Register this type. 40 | * \return The object TypeId. 41 | */ 42 | static TypeId GetTypeId(); 43 | TypeId GetInstanceTypeId() const override; 44 | 45 | QueueTag(); //!< Default constructor 46 | 47 | /** 48 | * Complete constructor. 49 | * \param id The queue id. 50 | */ 51 | QueueTag(uint32_t id); 52 | 53 | /** 54 | * Set the internal queue id. 55 | * \param id The queue id. 56 | */ 57 | void SetQueueId(uint32_t id); 58 | 59 | /** \return The queue id */ 60 | uint32_t GetQueueId() const; 61 | 62 | // Inherited from Tag 63 | void Serialize(TagBuffer i) const override; 64 | void Deserialize(TagBuffer i) override; 65 | uint32_t GetSerializedSize() const override; 66 | void Print(std::ostream& os) const override; 67 | 68 | private: 69 | uint32_t m_queueId; //!< Packet sequence number 70 | }; 71 | 72 | } // namespace ns3 73 | #endif // QUEUE_TAG_H 74 | -------------------------------------------------------------------------------- /model/tunnel-id-tag.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #include "tunnel-id-tag.h" 21 | 22 | #include 23 | 24 | namespace ns3 25 | { 26 | 27 | NS_LOG_COMPONENT_DEFINE("TunnelIdTag"); 28 | NS_OBJECT_ENSURE_REGISTERED(TunnelIdTag); 29 | 30 | TunnelIdTag::TunnelIdTag() 31 | : m_tunnelId(0) 32 | { 33 | } 34 | 35 | TunnelIdTag::TunnelIdTag(uint64_t id) 36 | : m_tunnelId(id) 37 | { 38 | } 39 | 40 | TypeId 41 | TunnelIdTag::GetTypeId() 42 | { 43 | static TypeId tid = TypeId("ns3::TunnelIdTag") 44 | .SetParent() 45 | .SetGroupName("OFSwitch13") 46 | .AddConstructor(); 47 | return tid; 48 | } 49 | 50 | TypeId 51 | TunnelIdTag::GetInstanceTypeId() const 52 | { 53 | return GetTypeId(); 54 | } 55 | 56 | void 57 | TunnelIdTag::SetTunnelId(uint64_t id) 58 | { 59 | m_tunnelId = id; 60 | } 61 | 62 | uint64_t 63 | TunnelIdTag::GetTunnelId() const 64 | { 65 | return m_tunnelId; 66 | } 67 | 68 | uint32_t 69 | TunnelIdTag::GetSerializedSize() const 70 | { 71 | return 8; 72 | } 73 | 74 | void 75 | TunnelIdTag::Serialize(TagBuffer i) const 76 | { 77 | i.WriteU64(m_tunnelId); 78 | } 79 | 80 | void 81 | TunnelIdTag::Deserialize(TagBuffer i) 82 | { 83 | m_tunnelId = i.ReadU64(); 84 | } 85 | 86 | void 87 | TunnelIdTag::Print(std::ostream& os) const 88 | { 89 | os << " TunnelIdTag id=" << m_tunnelId; 90 | } 91 | 92 | } // namespace ns3 93 | -------------------------------------------------------------------------------- /model/tunnel-id-tag.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 University of Campinas (Unicamp) 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License version 2 as 6 | * published by the Free Software Foundation; 7 | * 8 | * This program is distributed in the hope that it will be useful, 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | * GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License 14 | * along with this program; if not, write to the Free Software 15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | * 17 | * Author: Luciano Jerez Chaves 18 | */ 19 | 20 | #ifndef TUNNEL_ID_TAG_H 21 | #define TUNNEL_ID_TAG_H 22 | 23 | #include 24 | 25 | namespace ns3 26 | { 27 | 28 | class Tag; 29 | 30 | /** 31 | * \ingroup ofswitch13 32 | * Tag used to hold the tunnel metadata information (tunnel ID) when 33 | * sending/receiving a packet to/from a logical port device. 34 | */ 35 | class TunnelIdTag : public Tag 36 | { 37 | public: 38 | /** 39 | * Register this type. 40 | * \return The object TypeId. 41 | */ 42 | static TypeId GetTypeId(); 43 | TypeId GetInstanceTypeId() const override; 44 | 45 | TunnelIdTag(); //!< Default constructor 46 | 47 | /** 48 | * Complete constructor. 49 | * \param id The tunnel metadata information. 50 | */ 51 | TunnelIdTag(uint64_t id); 52 | 53 | /** 54 | * Set the internal tunnel metadata information. 55 | * \param id The tunnel metadata information. 56 | */ 57 | void SetTunnelId(uint64_t id); 58 | 59 | /** \return The tunnel metadata information */ 60 | uint64_t GetTunnelId() const; 61 | 62 | // Inherited from Tag 63 | void Serialize(TagBuffer i) const override; 64 | void Deserialize(TagBuffer i) override; 65 | uint32_t GetSerializedSize() const override; 66 | void Print(std::ostream& os) const override; 67 | 68 | private: 69 | uint64_t m_tunnelId; //!< Tunnel metadata information. 70 | }; 71 | 72 | } // namespace ns3 73 | #endif // TUNNEL_ID_TAG_H 74 | -------------------------------------------------------------------------------- /utils/ofswitch13-3_38.patch: -------------------------------------------------------------------------------- 1 | From 598058c4f0d47d8635b1b57d62068195cba7f006 Mon Sep 17 00:00:00 2001 2 | From: Luciano J Chaves 3 | Date: Fri, 1 Sep 2023 10:03:56 -0300 4 | Subject: [PATCH] OFSwitch13 patch 5 | 6 | --- 7 | .../custom-modules/ns3-configtable.cmake | 3 ++ 8 | src/csma/model/csma-net-device.cc | 35 +++++++++++++++++++ 9 | src/csma/model/csma-net-device.h | 13 +++++++ 10 | .../model/virtual-net-device.cc | 30 ++++++++++++++++ 11 | .../model/virtual-net-device.h | 11 ++++++ 12 | 5 files changed, 92 insertions(+) 13 | 14 | diff --git a/build-support/custom-modules/ns3-configtable.cmake b/build-support/custom-modules/ns3-configtable.cmake 15 | index c3baa514b..3b7434750 100644 16 | --- a/build-support/custom-modules/ns3-configtable.cmake 17 | +++ b/build-support/custom-modules/ns3-configtable.cmake 18 | @@ -161,6 +161,9 @@ macro(write_configtable) 19 | string(APPEND out "ns-3 Click Integration : ") 20 | check_on_or_off("ON" "${NS3_CLICK}") 21 | 22 | + string(APPEND out "ns-3 OFSwitch13 Integration : ") 23 | + check_on_or_off("ON" "${NS3_OFSWITCH13}") 24 | + 25 | string(APPEND out "ns-3 OpenFlow Integration : ") 26 | check_on_or_off("ON" "${NS3_OPENFLOW}") 27 | 28 | diff --git a/src/csma/model/csma-net-device.cc b/src/csma/model/csma-net-device.cc 29 | index 33d555e15..e10648f96 100644 30 | --- a/src/csma/model/csma-net-device.cc 31 | +++ b/src/csma/model/csma-net-device.cc 32 | @@ -806,6 +806,34 @@ CsmaNetDevice::Receive(Ptr packet, Ptr senderDevice) 33 | packetType = PACKET_OTHERHOST; 34 | } 35 | 36 | + // 37 | + // Check if this device is configure as an OpenFlow switch port. 38 | + // 39 | + if (!m_openFlowRxCallback.IsNull()) 40 | + { 41 | + // For all kinds of packet we receive, we hit the promiscuous sniffer 42 | + // hook. If the packet is addressed to this device (which is not supposed 43 | + // to happen in normal situations), we also hit the non-promiscuous 44 | + // sniffer hook, but in both cases we don't forward the packet up the 45 | + // stack. 46 | + m_promiscSnifferTrace(originalPacket); 47 | + if (packetType != PACKET_OTHERHOST) 48 | + { 49 | + m_snifferTrace(originalPacket); 50 | + } 51 | + 52 | + // We forward the original packet (which includes the EthernetHeader) to 53 | + // the OpenFlow receive callback for all kinds of packetType we receive 54 | + // (broadcast, multicast, host or other host). 55 | + m_openFlowRxCallback(this, 56 | + originalPacket, 57 | + protocol, 58 | + header.GetSource(), 59 | + header.GetDestination(), 60 | + packetType); 61 | + return; 62 | + } 63 | + 64 | // 65 | // For all kinds of packetType we receive, we hit the promiscuous sniffer 66 | // hook and pass a copy up to the promiscuous callback. Pass a copy to 67 | @@ -1024,6 +1052,13 @@ CsmaNetDevice::GetNode() const 68 | return m_node; 69 | } 70 | 71 | +void 72 | +CsmaNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) 73 | +{ 74 | + NS_LOG_FUNCTION(&cb); 75 | + m_openFlowRxCallback = cb; 76 | +} 77 | + 78 | void 79 | CsmaNetDevice::SetNode(Ptr node) 80 | { 81 | diff --git a/src/csma/model/csma-net-device.h b/src/csma/model/csma-net-device.h 82 | index 237daf37e..226ea7477 100644 83 | --- a/src/csma/model/csma-net-device.h 84 | +++ b/src/csma/model/csma-net-device.h 85 | @@ -312,6 +312,14 @@ class CsmaNetDevice : public NetDevice 86 | */ 87 | bool NeedsArp() const override; 88 | 89 | + /** 90 | + * Set the callback used to notify the OpenFlow when a packet has been 91 | + * received by this device. 92 | + * 93 | + * \param cb The callback. 94 | + */ 95 | + void SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb); 96 | + 97 | /** 98 | * Set the callback to be used to notify higher layers when a packet has been 99 | * received. 100 | @@ -692,6 +700,11 @@ class CsmaNetDevice : public NetDevice 101 | */ 102 | Mac48Address m_address; 103 | 104 | + /** 105 | + * The OpenFlow receive callback. 106 | + */ 107 | + NetDevice::PromiscReceiveCallback m_openFlowRxCallback; 108 | + 109 | /** 110 | * The callback used to notify higher layers that a packet has been received. 111 | */ 112 | diff --git a/src/virtual-net-device/model/virtual-net-device.cc b/src/virtual-net-device/model/virtual-net-device.cc 113 | index 6b19ef1d7..b6122ac71 100644 114 | --- a/src/virtual-net-device/model/virtual-net-device.cc 115 | +++ b/src/virtual-net-device/model/virtual-net-device.cc 116 | @@ -142,6 +142,29 @@ VirtualNetDevice::Receive(Ptr packet, 117 | const Address& destination, 118 | PacketType packetType) 119 | { 120 | + // 121 | + // Check if this device is configure as an OpenFlow switch port. 122 | + // 123 | + if (!m_openFlowRxCallback.IsNull()) 124 | + { 125 | + // For all kinds of packetType we receive, we hit the promiscuous sniffer 126 | + // hook. If the packet is addressed to this device (which is not supposed 127 | + // to happen in normal situations), we also hit the non-promiscuous 128 | + // sniffer hook, but in both cases we don't forward the packet up the 129 | + // stack. 130 | + m_promiscSnifferTrace(packet); 131 | + if (packetType != PACKET_OTHERHOST) 132 | + { 133 | + m_snifferTrace(packet); 134 | + } 135 | + 136 | + // We then forward the original packet to the OpenFlow receive callback 137 | + // for all kinds of packetType we receive (broadcast, multicast, host or 138 | + // other host). 139 | + m_openFlowRxCallback(this, packet, protocol, source, destination, packetType); 140 | + return true; 141 | + } 142 | + 143 | // 144 | // For all kinds of packetType we receive, we hit the promiscuous sniffer 145 | // hook and pass a copy up to the promiscuous callback. Pass a copy to 146 | @@ -319,4 +342,11 @@ VirtualNetDevice::IsBridge() const 147 | return false; 148 | } 149 | 150 | +void 151 | +VirtualNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) 152 | +{ 153 | + NS_LOG_FUNCTION(&cb); 154 | + m_openFlowRxCallback = cb; 155 | +} 156 | + 157 | } // namespace ns3 158 | diff --git a/src/virtual-net-device/model/virtual-net-device.h b/src/virtual-net-device/model/virtual-net-device.h 159 | index 66718596a..c0eb0c468 100644 160 | --- a/src/virtual-net-device/model/virtual-net-device.h 161 | +++ b/src/virtual-net-device/model/virtual-net-device.h 162 | @@ -153,6 +153,14 @@ class VirtualNetDevice : public NetDevice 163 | bool SupportsSendFrom() const override; 164 | bool IsBridge() const override; 165 | 166 | + /** 167 | + * Set the callback used to notify the OpenFlow when a packet has been 168 | + * received by this device. 169 | + * 170 | + * \param cb The OpenFlow receive callback. 171 | + */ 172 | + void SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb); 173 | + 174 | protected: 175 | void DoDispose() override; 176 | 177 | @@ -173,6 +181,9 @@ class VirtualNetDevice : public NetDevice 178 | bool m_needsArp; //!< True if the device needs ARP 179 | bool m_supportsSendFrom; //!< True if the device supports SendFrm 180 | bool m_isPointToPoint; //!< True if the device is a PointToPoint type device 181 | + 182 | + /** The OpenFlow receive callback. */ 183 | + NetDevice::PromiscReceiveCallback m_openFlowRxCallback; 184 | }; 185 | 186 | } // namespace ns3 187 | -- 188 | 2.34.1 189 | 190 | -------------------------------------------------------------------------------- /utils/ofswitch13-3_39.patch: -------------------------------------------------------------------------------- 1 | From b89fa2043c3af1edd2270eb375756d6525bff331 Mon Sep 17 00:00:00 2001 2 | From: Luciano J Chaves 3 | Date: Fri, 1 Sep 2023 09:53:24 -0300 4 | Subject: [PATCH] OFSwitch13 patch 5 | 6 | --- 7 | .../custom-modules/ns3-configtable.cmake | 3 ++ 8 | src/csma/model/csma-net-device.cc | 35 +++++++++++++++++++ 9 | src/csma/model/csma-net-device.h | 13 +++++++ 10 | .../model/virtual-net-device.cc | 30 ++++++++++++++++ 11 | .../model/virtual-net-device.h | 11 ++++++ 12 | 5 files changed, 92 insertions(+) 13 | 14 | diff --git a/build-support/custom-modules/ns3-configtable.cmake b/build-support/custom-modules/ns3-configtable.cmake 15 | index c3baa514b..3b7434750 100644 16 | --- a/build-support/custom-modules/ns3-configtable.cmake 17 | +++ b/build-support/custom-modules/ns3-configtable.cmake 18 | @@ -161,6 +161,9 @@ macro(write_configtable) 19 | string(APPEND out "ns-3 Click Integration : ") 20 | check_on_or_off("ON" "${NS3_CLICK}") 21 | 22 | + string(APPEND out "ns-3 OFSwitch13 Integration : ") 23 | + check_on_or_off("ON" "${NS3_OFSWITCH13}") 24 | + 25 | string(APPEND out "ns-3 OpenFlow Integration : ") 26 | check_on_or_off("ON" "${NS3_OPENFLOW}") 27 | 28 | diff --git a/src/csma/model/csma-net-device.cc b/src/csma/model/csma-net-device.cc 29 | index bb0b93894..f6d3ff4ae 100644 30 | --- a/src/csma/model/csma-net-device.cc 31 | +++ b/src/csma/model/csma-net-device.cc 32 | @@ -806,6 +806,34 @@ CsmaNetDevice::Receive(Ptr packet, Ptr senderDevice) 33 | packetType = PACKET_OTHERHOST; 34 | } 35 | 36 | + // 37 | + // Check if this device is configure as an OpenFlow switch port. 38 | + // 39 | + if (!m_openFlowRxCallback.IsNull()) 40 | + { 41 | + // For all kinds of packet we receive, we hit the promiscuous sniffer 42 | + // hook. If the packet is addressed to this device (which is not supposed 43 | + // to happen in normal situations), we also hit the non-promiscuous 44 | + // sniffer hook, but in both cases we don't forward the packet up the 45 | + // stack. 46 | + m_promiscSnifferTrace(originalPacket); 47 | + if (packetType != PACKET_OTHERHOST) 48 | + { 49 | + m_snifferTrace(originalPacket); 50 | + } 51 | + 52 | + // We forward the original packet (which includes the EthernetHeader) to 53 | + // the OpenFlow receive callback for all kinds of packetType we receive 54 | + // (broadcast, multicast, host or other host). 55 | + m_openFlowRxCallback(this, 56 | + originalPacket, 57 | + protocol, 58 | + header.GetSource(), 59 | + header.GetDestination(), 60 | + packetType); 61 | + return; 62 | + } 63 | + 64 | // 65 | // For all kinds of packetType we receive, we hit the promiscuous sniffer 66 | // hook and pass a copy up to the promiscuous callback. Pass a copy to 67 | @@ -1024,6 +1052,13 @@ CsmaNetDevice::GetNode() const 68 | return m_node; 69 | } 70 | 71 | +void 72 | +CsmaNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) 73 | +{ 74 | + NS_LOG_FUNCTION(&cb); 75 | + m_openFlowRxCallback = cb; 76 | +} 77 | + 78 | void 79 | CsmaNetDevice::SetNode(Ptr node) 80 | { 81 | diff --git a/src/csma/model/csma-net-device.h b/src/csma/model/csma-net-device.h 82 | index 237daf37e..226ea7477 100644 83 | --- a/src/csma/model/csma-net-device.h 84 | +++ b/src/csma/model/csma-net-device.h 85 | @@ -312,6 +312,14 @@ class CsmaNetDevice : public NetDevice 86 | */ 87 | bool NeedsArp() const override; 88 | 89 | + /** 90 | + * Set the callback used to notify the OpenFlow when a packet has been 91 | + * received by this device. 92 | + * 93 | + * \param cb The callback. 94 | + */ 95 | + void SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb); 96 | + 97 | /** 98 | * Set the callback to be used to notify higher layers when a packet has been 99 | * received. 100 | @@ -692,6 +700,11 @@ class CsmaNetDevice : public NetDevice 101 | */ 102 | Mac48Address m_address; 103 | 104 | + /** 105 | + * The OpenFlow receive callback. 106 | + */ 107 | + NetDevice::PromiscReceiveCallback m_openFlowRxCallback; 108 | + 109 | /** 110 | * The callback used to notify higher layers that a packet has been received. 111 | */ 112 | diff --git a/src/virtual-net-device/model/virtual-net-device.cc b/src/virtual-net-device/model/virtual-net-device.cc 113 | index 31518b7dc..e7613508f 100644 114 | --- a/src/virtual-net-device/model/virtual-net-device.cc 115 | +++ b/src/virtual-net-device/model/virtual-net-device.cc 116 | @@ -142,6 +142,29 @@ VirtualNetDevice::Receive(Ptr packet, 117 | const Address& destination, 118 | PacketType packetType) 119 | { 120 | + // 121 | + // Check if this device is configure as an OpenFlow switch port. 122 | + // 123 | + if (!m_openFlowRxCallback.IsNull()) 124 | + { 125 | + // For all kinds of packetType we receive, we hit the promiscuous sniffer 126 | + // hook. If the packet is addressed to this device (which is not supposed 127 | + // to happen in normal situations), we also hit the non-promiscuous 128 | + // sniffer hook, but in both cases we don't forward the packet up the 129 | + // stack. 130 | + m_promiscSnifferTrace(packet); 131 | + if (packetType != PACKET_OTHERHOST) 132 | + { 133 | + m_snifferTrace(packet); 134 | + } 135 | + 136 | + // We then forward the original packet to the OpenFlow receive callback 137 | + // for all kinds of packetType we receive (broadcast, multicast, host or 138 | + // other host). 139 | + m_openFlowRxCallback(this, packet, protocol, source, destination, packetType); 140 | + return true; 141 | + } 142 | + 143 | // 144 | // For all kinds of packetType we receive, we hit the promiscuous sniffer 145 | // hook and pass a copy up to the promiscuous callback. Pass a copy to 146 | @@ -311,4 +334,11 @@ VirtualNetDevice::IsBridge() const 147 | return false; 148 | } 149 | 150 | +void 151 | +VirtualNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) 152 | +{ 153 | + NS_LOG_FUNCTION(&cb); 154 | + m_openFlowRxCallback = cb; 155 | +} 156 | + 157 | } // namespace ns3 158 | diff --git a/src/virtual-net-device/model/virtual-net-device.h b/src/virtual-net-device/model/virtual-net-device.h 159 | index 66718596a..c0eb0c468 100644 160 | --- a/src/virtual-net-device/model/virtual-net-device.h 161 | +++ b/src/virtual-net-device/model/virtual-net-device.h 162 | @@ -153,6 +153,14 @@ class VirtualNetDevice : public NetDevice 163 | bool SupportsSendFrom() const override; 164 | bool IsBridge() const override; 165 | 166 | + /** 167 | + * Set the callback used to notify the OpenFlow when a packet has been 168 | + * received by this device. 169 | + * 170 | + * \param cb The OpenFlow receive callback. 171 | + */ 172 | + void SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb); 173 | + 174 | protected: 175 | void DoDispose() override; 176 | 177 | @@ -173,6 +181,9 @@ class VirtualNetDevice : public NetDevice 178 | bool m_needsArp; //!< True if the device needs ARP 179 | bool m_supportsSendFrom; //!< True if the device supports SendFrm 180 | bool m_isPointToPoint; //!< True if the device is a PointToPoint type device 181 | + 182 | + /** The OpenFlow receive callback. */ 183 | + NetDevice::PromiscReceiveCallback m_openFlowRxCallback; 184 | }; 185 | 186 | } // namespace ns3 187 | -- 188 | 2.34.1 189 | 190 | -------------------------------------------------------------------------------- /utils/ofswitch13-3_40.patch: -------------------------------------------------------------------------------- 1 | From 2ddd4f2187ac73c4024d7252ae3b9816116f811a Mon Sep 17 00:00:00 2001 2 | From: Luciano J Chaves 3 | Date: Wed, 11 Oct 2023 09:49:03 -0300 4 | Subject: [PATCH] OFSwitch13 patch 5 | 6 | --- 7 | .../custom-modules/ns3-configtable.cmake | 3 ++ 8 | src/csma/model/csma-net-device.cc | 35 +++++++++++++++++++ 9 | src/csma/model/csma-net-device.h | 13 +++++++ 10 | .../model/virtual-net-device.cc | 30 ++++++++++++++++ 11 | .../model/virtual-net-device.h | 11 ++++++ 12 | 5 files changed, 92 insertions(+) 13 | 14 | diff --git a/build-support/custom-modules/ns3-configtable.cmake b/build-support/custom-modules/ns3-configtable.cmake 15 | index 6de18dd2d..bdcf266cf 100644 16 | --- a/build-support/custom-modules/ns3-configtable.cmake 17 | +++ b/build-support/custom-modules/ns3-configtable.cmake 18 | @@ -169,6 +169,9 @@ macro(write_configtable) 19 | string(APPEND out "ns-3 Click Integration : ") 20 | check_on_or_off("ON" "NS3_CLICK") 21 | 22 | + string(APPEND out "ns-3 OFSwitch13 Integration : ") 23 | + check_on_or_off("ON" "NS3_OFSWITCH13") 24 | + 25 | string(APPEND out "ns-3 OpenFlow Integration : ") 26 | check_on_or_off("ON" "NS3_OPENFLOW") 27 | 28 | diff --git a/src/csma/model/csma-net-device.cc b/src/csma/model/csma-net-device.cc 29 | index bb0b93894..f6d3ff4ae 100644 30 | --- a/src/csma/model/csma-net-device.cc 31 | +++ b/src/csma/model/csma-net-device.cc 32 | @@ -806,6 +806,34 @@ CsmaNetDevice::Receive(Ptr packet, Ptr senderDevice) 33 | packetType = PACKET_OTHERHOST; 34 | } 35 | 36 | + // 37 | + // Check if this device is configure as an OpenFlow switch port. 38 | + // 39 | + if (!m_openFlowRxCallback.IsNull()) 40 | + { 41 | + // For all kinds of packet we receive, we hit the promiscuous sniffer 42 | + // hook. If the packet is addressed to this device (which is not supposed 43 | + // to happen in normal situations), we also hit the non-promiscuous 44 | + // sniffer hook, but in both cases we don't forward the packet up the 45 | + // stack. 46 | + m_promiscSnifferTrace(originalPacket); 47 | + if (packetType != PACKET_OTHERHOST) 48 | + { 49 | + m_snifferTrace(originalPacket); 50 | + } 51 | + 52 | + // We forward the original packet (which includes the EthernetHeader) to 53 | + // the OpenFlow receive callback for all kinds of packetType we receive 54 | + // (broadcast, multicast, host or other host). 55 | + m_openFlowRxCallback(this, 56 | + originalPacket, 57 | + protocol, 58 | + header.GetSource(), 59 | + header.GetDestination(), 60 | + packetType); 61 | + return; 62 | + } 63 | + 64 | // 65 | // For all kinds of packetType we receive, we hit the promiscuous sniffer 66 | // hook and pass a copy up to the promiscuous callback. Pass a copy to 67 | @@ -1024,6 +1052,13 @@ CsmaNetDevice::GetNode() const 68 | return m_node; 69 | } 70 | 71 | +void 72 | +CsmaNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) 73 | +{ 74 | + NS_LOG_FUNCTION(&cb); 75 | + m_openFlowRxCallback = cb; 76 | +} 77 | + 78 | void 79 | CsmaNetDevice::SetNode(Ptr node) 80 | { 81 | diff --git a/src/csma/model/csma-net-device.h b/src/csma/model/csma-net-device.h 82 | index ff72aad2a..c65304e02 100644 83 | --- a/src/csma/model/csma-net-device.h 84 | +++ b/src/csma/model/csma-net-device.h 85 | @@ -313,6 +313,14 @@ class CsmaNetDevice : public NetDevice 86 | */ 87 | bool NeedsArp() const override; 88 | 89 | + /** 90 | + * Set the callback used to notify the OpenFlow when a packet has been 91 | + * received by this device. 92 | + * 93 | + * \param cb The callback. 94 | + */ 95 | + void SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb); 96 | + 97 | /** 98 | * Set the callback to be used to notify higher layers when a packet has been 99 | * received. 100 | @@ -693,6 +701,11 @@ class CsmaNetDevice : public NetDevice 101 | */ 102 | Mac48Address m_address; 103 | 104 | + /** 105 | + * The OpenFlow receive callback. 106 | + */ 107 | + NetDevice::PromiscReceiveCallback m_openFlowRxCallback; 108 | + 109 | /** 110 | * The callback used to notify higher layers that a packet has been received. 111 | */ 112 | diff --git a/src/virtual-net-device/model/virtual-net-device.cc b/src/virtual-net-device/model/virtual-net-device.cc 113 | index 31518b7dc..e7613508f 100644 114 | --- a/src/virtual-net-device/model/virtual-net-device.cc 115 | +++ b/src/virtual-net-device/model/virtual-net-device.cc 116 | @@ -142,6 +142,29 @@ VirtualNetDevice::Receive(Ptr packet, 117 | const Address& destination, 118 | PacketType packetType) 119 | { 120 | + // 121 | + // Check if this device is configure as an OpenFlow switch port. 122 | + // 123 | + if (!m_openFlowRxCallback.IsNull()) 124 | + { 125 | + // For all kinds of packetType we receive, we hit the promiscuous sniffer 126 | + // hook. If the packet is addressed to this device (which is not supposed 127 | + // to happen in normal situations), we also hit the non-promiscuous 128 | + // sniffer hook, but in both cases we don't forward the packet up the 129 | + // stack. 130 | + m_promiscSnifferTrace(packet); 131 | + if (packetType != PACKET_OTHERHOST) 132 | + { 133 | + m_snifferTrace(packet); 134 | + } 135 | + 136 | + // We then forward the original packet to the OpenFlow receive callback 137 | + // for all kinds of packetType we receive (broadcast, multicast, host or 138 | + // other host). 139 | + m_openFlowRxCallback(this, packet, protocol, source, destination, packetType); 140 | + return true; 141 | + } 142 | + 143 | // 144 | // For all kinds of packetType we receive, we hit the promiscuous sniffer 145 | // hook and pass a copy up to the promiscuous callback. Pass a copy to 146 | @@ -311,4 +334,11 @@ VirtualNetDevice::IsBridge() const 147 | return false; 148 | } 149 | 150 | +void 151 | +VirtualNetDevice::SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb) 152 | +{ 153 | + NS_LOG_FUNCTION(&cb); 154 | + m_openFlowRxCallback = cb; 155 | +} 156 | + 157 | } // namespace ns3 158 | diff --git a/src/virtual-net-device/model/virtual-net-device.h b/src/virtual-net-device/model/virtual-net-device.h 159 | index 66718596a..c0eb0c468 100644 160 | --- a/src/virtual-net-device/model/virtual-net-device.h 161 | +++ b/src/virtual-net-device/model/virtual-net-device.h 162 | @@ -153,6 +153,14 @@ class VirtualNetDevice : public NetDevice 163 | bool SupportsSendFrom() const override; 164 | bool IsBridge() const override; 165 | 166 | + /** 167 | + * Set the callback used to notify the OpenFlow when a packet has been 168 | + * received by this device. 169 | + * 170 | + * \param cb The OpenFlow receive callback. 171 | + */ 172 | + void SetOpenFlowReceiveCallback(NetDevice::PromiscReceiveCallback cb); 173 | + 174 | protected: 175 | void DoDispose() override; 176 | 177 | @@ -173,6 +181,9 @@ class VirtualNetDevice : public NetDevice 178 | bool m_needsArp; //!< True if the device needs ARP 179 | bool m_supportsSendFrom; //!< True if the device supports SendFrm 180 | bool m_isPointToPoint; //!< True if the device is a PointToPoint type device 181 | + 182 | + /** The OpenFlow receive callback. */ 183 | + NetDevice::PromiscReceiveCallback m_openFlowRxCallback; 184 | }; 185 | 186 | } // namespace ns3 187 | -- 188 | 2.34.1 189 | 190 | --------------------------------------------------------------------------------