Глава 3. Организация проекта
В данной главе рассматривается три варианта организации проекта (дерева его папок). Для наиболее гибкого варианта мы создадим минимальный код проекта, скомпилируем и запустим его примеры и файл симуляции.
Организация проекта, зависит от уровня задачи, которую предстоит решать:
уровень Быстрое тестирование
уровень Серьезный проект
уровень Исследование
Рассмотрим каждый из уровней по порядку.
1.1 Быстрое тестирование
Для проведения быстрого тестирования, изучения API или реализации небольших одноразовых экспериментов наиболее подходящей является директория scratch - папка внутри директории ns-3.45, где CMake по умолчанию осуществляет поиск и компиляцию ваших сценариев.
Плюсы:
Проста в использовании: пользователь создает C++-файл теста в директории scratch/ и запускает симуляцию командой:
./ns3 run my-test.Не требует никакой дополнительной настройки, если вы разрабатываете примеры или тесты для какого-то модуля и располагаете их по правилам, т.е. внутри директории модуля, то каждый новый тест вам придется вручную прописывать в соответствующие CMake-файлы. В то время как в папке scratch это произойдет автоматом при запуске компиляции.
Минусы:
Отсутствие масштабирования: все ваши файлы «лежат в одной куче»;
Трудности в повторном использовании: код, написанный для одного эксперимента, сложно использовать в другом.
Смешение логики: в одном файле смешаны и настройка топологии, и реализация нового приложения/протокола, и запуск симуляции.
Вывод: scratch — это «черновик», не подходящий для реализации серьезного проекта. Но если вы добавляете в ваш серьезный проект новы тест, то удобнее сналала его отладить в папке scratch, а затем перенести в проект уже работающий должным образом код.
1.2 Профессиональный подход
Профессиональны подход состоит в создании собственного модуля, что является правильным способом организации кода в NS-3. Мы инкапсулируем свою логику (новые приложения, протоколы, модели) в отдельный модуль, который имеет тот же вид, что и стандартные модули NS-3 (internet, wifi, point-to-point и т.д.).
Плюсы:
Код логично сгруппирован;
Имеется возможность использовать новый модуль в разных симуляционных сценариях;
Детали реализации скрыты от пользователя модуля, который работает с ним через простые Helper-классы;
Модуль становится частью системы сборки NS-3.
Минусы:
Медленный старт: требуется время на организацию дерева проекта и настройку сборки.
Как создать свой модуль?
Для этой цели в к NS-3 имеется специальная утилита: create-module.py. Переходим в корень директории ns-3.45:
$ cd ~/workspace_ns3.45/ns-allinone-3.45/ns-3.45
Имя модуля может состоять из следующих символов: букв, цифр, символов “'-” и “_”. Запустим утилиту, предположим, что мы хотим создать модуль с именем my-new-module:
$ ./utils/create-module.py my-new-module
Утилита выводит примерно такой ответ:
$ Creating module ~/workspace_ns3.45/ns-allinone-3.45/ns-3.45/contrib/my-new-module Successfully created new modules Run './ns3 configure' to include them in the build
Эта команда создаст директорию contrib/my-new-module/ со структурой, показанной в листинге 1.1.
Листинг 1.1: Дерево файлов модуля my_new_module |-- CMakeLists.txt |-- doc # Documentation (Doxygen) | `-- my-new-module.rst |-- examples # Usage examples for your module | |-- CMakeLists.txt | `-- my-new-module-example.cc |-- helper # Helper classes for simplifying setup | |-- my-new-module-helper.cc | `-- my-new-module-helper.h |-- model # Main implementation of your classes | | # (applications, protocols) | |---my-new-module.cc | `---my-new-module.h `-- test # Unit tests for your code `---my-new-module-test-suite.cc
В директориях утилита также создаст файлы-заготовки, модуль сразу получается пригодным для компиляции.
Что где располагать
model/: Если моделируется новый модуль (например, протокол маршрутизации) MyNewModule, здесь располагаются my-new-module.cc и my-new-module.h.
helper/: Здесь располагаются my-new-module-helper.cc и my-new-model-helper.h. Этот класс помогает пользователям устанавливать протокол на узлы, выполнить настройки по умолчанию.
examples/: Небольшие сценарии-примеры, демонстрирующие, как использовать MyNewModuleHelper.
Если проект содержит несколько модулей, можно передать утилите название проекта, и она создаст в директории contrib директорию с именем проекта, а модули поместит уже в неё:
$ ./utils/create-module.py --project PROJECT module1 module2 module3
Каждый из модулей будет сразу готов к компиляции, но придется еще добавить в корень проекта файл CMakeLists.txt. Полную справку по аргументам командной строки и описание работы утилиты можно получить обычным способом:
$ ./utils/create-module.py -h
Чтобы симулятор начал использовать новые модули (это же касается и тестов), после их создания необходимо вызвать команду:
$ ./ns3 configure --enable-examples --enable-tests
1.3 Большой проект
Когда у нас есть свой модуль, то сама симуляция (сценарий) — это всего лишь программа, использующая этот модуль. Поэтому лучше всего отделить код модуля от кода сценария. Наиболее гибким решением является вынос файлов модулей и симуляций за пределы кодовой базы симулятора. В листинге 1.2 показывается структура для большого исследовательского проекта:
Листинг 1.2: Дерево файлов большого проекта big-ns3-project |--- ns-3.45 # Link to the NS-3 source code | `--- contrib | `--- my-cool-protocol/ # Your custom module, created via | # the create-module.py utility |--- simulations/ # <--- IMPORTANT: Your experiment scripts go here! |--- results/ # <--- Raw simulation results |--- analysis/ # <--- Scripts for data processing and analysis |---plots/ # <--- Final plots and figures for publications |---doc/ # Project documentation | `-- project_description.md |--- README.md # Main project file: how to build and run `---.gitignore # Git ignore file
Для создания такого дерева проекта создана «питоновская» утилита create_ns_project, которую можно скачать с Github.com
Пример создания проекта
Создание директории внешних модулей
В симуляторе NS-3 действует соглашение, согласно которому, исходный код внешних модулей должен располагаться в директории с названием ns-3-external-contrib*. Она, в свою очередь, должна располагаться на одном уровне с директорией ns3.45. Создаем директорию внешних модулей командой:
$ mkdir ~/workspace_ns3.45/ns-allinone-3.45/ns-3-external-contrib
Создание дерева проекта
Далее создаем дерево проекта. Для этого запускаем утилиту create_ns_project, передав ей в качестве аргументов название проекта и путь к папке внешних модулей. Пусть наш проект будет иметь название «my_project»:
$ python ./create_ns_project.py -p my_project -o ~/workspace_ns3.45/ns-allinone-3.45/ns-3-external-contrib
В случае успеха выводится сообщение:
Project 'my_project' created successfully! Navigate to the directory: cd /home/igor/workspace_ns3.45/ns-allinone-3.45/ns-3-external-contrib/my_project Read README.md for instructions on integrating with NS-3.
В результате работы утилиты в директории ns-3-external-contrib создается проект с именем my_project.
Создание символической ссылки на директорию ns3.45
Для удобства работы с утилитами находящимися в папке симулятора, создадим внутри проекта символическую ссылку на эту папку:
$ ln -s ~/workspace_ns3.45/ns-allinone-3.45/ns-3.45 ~/workspace_ns3.45/ns-allinone-3.45/ns-3-external-contrib/my_project/ns-3.45
Создание модуля в проекте
Переходим в папку проекта:
$ cd ~/workspace_ns3.45/ns-allinone-3.45/ns-3-external-contrib/my_project
Предположим, что необходимо создать модуль my_module. Тогда вызов утилиты create-module имеет вид:
$ ./ns-3.45/utils/create-module.py my_module
В случае успеха выводится сообщение:
Creating module /home/igor/workspace_ns3.45/ns-allinone-3.45/ns-3-external-contrib/my_project/contrib/my_module Successfully created new modules Run './ns3 configure' to include them in the build
В папке contrib появляется дерево папок модуля my_module со всеми необходимыми для сборки модуля файлами.
Добавление в проект основного файла CMakeLists.txt
Добавляем в корневой каталог проекта файл CMakeLists.txt со следующим содержанием:
cmake_minimum_required(VERSION 3.10) project(MyProject) add_subdirectory(contrib)
Добавление файла CMakeLists.txt в директорию contrib
Добавляем в директорию contrib файл CMakeLists.txt со следующим содержанием:
add_subdirectory(my_module)
В данный момент файл содержит ссылку на директорию модуля. При добавлении в проект новых модулей, ссылки на их директории также необходимо добавить в этот файл.
Сборка и запуск примера использования модуля my_module
Выполняем конфигурирование сборки файлов:
$ ./ns3 configure --enable-examples --enable-tests
Выполняем сборку модулей и файлов симуляции:
$ ./ns3 build
Если сборка проходит без ошибок, то в списке целей сборки, который можно получить командой:
$ ./ns3 show targets
появляется цель, соответствующая нашему модулю, с именем my_module-example, эту цель необходимо использовать для запуска примера симуляции:
$ ./ns3 run my_module-example
В ответ мы получаем сообщение:
[0/2] Re-checking globbed directories... ninja: no work to do.
Так как файл примера создан автоматически - в нем еще нет полезного функционала, результат симуляции содержит только эти две строчки.
Сборка и моделирование проекта
Создаем в директории simulations сценарий my_project-simulation.cc, со следующим содержанием:
// simulations/my_project-simulation.cc #include "ns3/core-module.h" #include "ns3/my_module-helper.h" /** * @file * * Explain here what the example does. */ using namespace ns3; int main(int argc, char* argv[]) { bool verbose = true; CommandLine cmd(__FILE__); cmd.AddValue("verbose", "Tell application to log if true", verbose); cmd.Parse(argc, argv); /* ... */ NS_LOG_UNCOND("My Project simulation Hello"); Simulator::Run(); Simulator::Destroy(); return 0; }
В отличие от файлов по умолчанию, при запуске этот файл выводит сообщение «My Project simulation Hello». В этом мы убедимся ниже, запустив симуляцию. Добавляем в эту же директорию файл CMakeLists.txt со следующим содержанием:
# simulations/CMakeLists.txt # Create an executable for our simulation add_executable(my_project-simulation my_project-simulation.cc) # Specify the libraries to link against target_link_libraries(my_project-simulation core network my_module ) # Define the path to the build directory set(BUILD_DIR ${CMAKE_SOURCE_DIR}/build) # Create the simulation directory inside the build directory file(MAKE_DIRECTORY ${BUILD_DIR}/simulation) # Set the output directory to build/simulation set_target_properties(my_project-simulation PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${BUILD_DIR}/simulation )
Изменяем файл CMakeLists.txt в корневом каталоге проекта, дополнив его строчкой add_subdirectory(simulations), теперь он будет выглядеть так:
# my_project/CMakeLists.txt cmake_minimum_required(VERSION 3.10) project(MyProject) add_subdirectory(contrib) add_subdirectory(simulations)
Выполняем конфигурирование сборки файлов:
$ ./ns3 configure --enable-examples --enable-tests
Выполняем сборку модулей и файлов симуляции:
$ ./ns3 build
В отличие от файлов примеров, мы не обнаружим цель файла симуляции в выводе команды:
$ ./ns3 show targets
по этой причине для его запуска не удастся использовать команду:
$ ./ns3 run my_module-example
Вместо этого осуществляем прямой запуск исполняемого файла:
$ ./build/simulation/my_project-simulation
Во время выполнения симуляция выведет сообщение:
My Project simulation Hello
После добавления необходимых файлов дерево проекта принимает следующий вид:
Листинг 1.3: Итоговое дерево файлов проекта my-project |-- about_folder.md |-- analysis | `-- about_folder.md |-- CMakeLists.txt |-- contrib | |-- about_folder.md | |-- CMakeLists.txt | `-- my_module | |-- CMakeLists.txt | |-- doc | | `-- my_module.rst | |-- examples | | |-- CMakeLists.txt | | `-- my_module-example.cc | |-- helper | | |-- my_module-helper.cc | | `-- my_module-helper.h | |-- model | | |-- my_module.cc | | `-- my_module.h | `-- test | `-- my_module-test-suite.cc |-- doc | `-- about_folder.md |-- plots | `-- about_folder.md |-- README.md |-- results | `-- about_folder.md |-- simulations | |-- about_folder.md | |-- CMakeLists.txt | `-- my_project-simulation.cc `-- src `-- about_folder.md
Теперь каталог проекта готов к разработке модулей и симуляции.
Мы рассмотрели способы организации проекта, их преимущества и недостатки. На сегодня это всё. В следующей статье мы приступим к изучению модуля спутниковой связи Satellite.
Работа выполнена в рамках Программы создания и развития центра НТИ на базе МФТИ, Физтех по направлению («сквозной» технологии) Национальной технологической инициативы «Перспективные технологии для космических систем и сервисов» при реализации комплексного научно-исследовательского и опытно-конструкторского проекта “Разработка комплексной среды моделирования и проектирования гибридных инфокоммуникационных сетей наземного, стратосферного и космического сегментов с использованием параметрического и структурного синтеза”.