Это команда ns-3-tutorial, которую можно запустить в бесплатном хостинг-провайдере OnWorks, используя одну из наших многочисленных бесплатных онлайн-рабочих станций, таких как Ubuntu Online, Fedora Online, онлайн-эмулятор Windows или онлайн-эмулятор MAC OS.
ПРОГРАММА:
ИМЯ
ns-3-tutorial - Учебное пособие по ns-3
Это нс-3 Обучение. Первичная документация по проекту НС-3 имеется в пяти
формы:
· нс-3 Доксиген: Документация общедоступных API симулятора.
· Руководство (этот документ), Руководство и Библиотека моделей для последний освободить и
способствовали дерево
· нс-3 Вики
Этот документ написан на ReStructuredText для Сфинкс и поддерживается в
документ / учебник каталог исходного кода ns-3.
ВВЕДЕНИЕ
Команда нс-3 simulator - это симулятор сети с дискретными событиями, предназначенный в первую очередь для исследований
и образовательное использование. В нс-3 Проект, запущенный в 2006 году, представляет собой проект с открытым исходным кодом.
развивающийся нс-3.
Цель этого урока - познакомить с новыми нс-3 пользователей в систему в структурированном
способ. Новым пользователям иногда трудно почерпнуть важную информацию из подробных
руководства и преобразовать эту информацию в рабочие модели. В этом уроке мы
построит несколько примеров моделирования, представляя и объясняя ключевые концепции и
особенности, как мы идем.
По мере развертывания учебника мы представим полную нс-3 документацию и предоставить
указатели на исходный код для тех, кто заинтересован в более глубоком изучении работы
системы.
С самого начала стоит отметить несколько ключевых моментов:
· нс-3 является открытым исходным кодом, и проект стремится поддерживать открытую среду для
исследователи вносят свой вклад и делятся своим программным обеспечением.
· нс-3 не является обратно совместимым расширением нс-2; это новый симулятор. Два
симуляторы написаны на C ++, но нс-3 это новый симулятор, который не поддерживает
нс-2 API. Некоторые модели из нс-2 уже были перенесены из нс-2 в нс-3,
проект будет продолжать поддерживать нс-2 в то время как нс-3 строится, и буду изучать
механизмы перехода и интеграции.
О нас нс-3
нс-3 был разработан, чтобы предоставить открытую расширяемую платформу сетевого моделирования для
сетевые исследования и образование. Вкратце, нс-3 предоставляет модели того, как пакетные данные
сети работают и работают, а также предоставляет пользователям возможность моделирования
имитационные эксперименты. Некоторые из причин использовать нс-3 включать в себя исследования, которые
труднее или невозможно выполнить с реальными системами, изучить поведение системы
в строго контролируемой воспроизводимой среде и узнать о том, как работают сети.
Пользователи заметят, что доступная модель установлена в нс-3 фокусируется на моделировании того, как Интернет
протоколы и сети работают, но нс-3 не ограничивается интернет-системами; несколько пользователей
используют нс-3 для моделирования систем, не основанных на Интернете.
Для исследований сетевого моделирования существует множество инструментов моделирования. Ниже приведены несколько
отличительные черты нс-3 в отличие от других инструментов.
· нс-3 разработан как набор библиотек, которые можно комбинировать вместе, а также с другими
внешние программные библиотеки. Хотя некоторые платформы моделирования предоставляют пользователям
единая интегрированная среда графического пользовательского интерфейса, в которой выполняются все задачи
из, нс-3 в этом отношении более модульный. Несколько внешних аниматоров и анализ данных
и инструменты визуализации можно использовать с нс-3. Однако пользователям следует ожидать, что они будут работать с
в командной строке и с инструментами разработки программного обеспечения C ++ и / или Python.
· нс-3 в основном используется в системах Linux, хотя существует поддержка FreeBSD, Cygwin.
(для Windows), а встроенная поддержка Windows Visual Studio находится в процессе
разработаны.
· нс-3 не является официально поддерживаемым программным продуктом какой-либо компании. Поддержка для нс-3
делается по принципу «максимальных усилий» в списке рассылки ns-3-users.
Что касается нс-2 Пользователи
Для тех, кто знаком с нс-2 (популярный инструмент, предшествовавший нс-3), наиболее заметный снаружи
изменить при переходе на нс-3 это выбор языка сценариев. Программы в нс-2
написаны в OTcl, а результаты моделирования могут быть визуализированы с помощью Network Animator.
нам. Невозможно запустить моделирование в нс-2 чисто из C ++ (т.е. как main ()
программа без всяких OTcl). Более того, некоторые компоненты нс-2 написаны на C ++ и
другие в OTcl. В нс-3, симулятор полностью написан на C ++, с дополнительным Python
привязки. Таким образом, сценарии моделирования могут быть написаны на C ++ или Python. Новые аниматоры
и визуализаторы доступны и находятся в стадии разработки. С нс-3 генерирует pcap
файлы трассировки пакетов, другие утилиты также могут быть использованы для анализа трассировки. В этом
руководство, мы сначала сконцентрируемся на написании сценариев непосредственно на C ++ и интерпретации результатов
через файлы трассировки.
Но есть и сходства (оба, например, основаны на объектах C ++, а некоторые
код из нс-2 уже был перенесен на нс-3). Постараемся выделить отличия
между нс-2 и нс-3 как мы продолжим в этом уроке.
Мы часто слышим вопрос: "Стоит ли мне по-прежнему использовать нс-2 или переехать в нс-3?" В этом
мнение автора, если пользователь каким-либо образом не имеет нс-2 (либо на основе существующих
личный комфорт и знание нс-2, или на основе конкретной имитационной модели, которая
доступно только в нс-2), пользователь будет более продуктивным с нс-3 для следующих
причины:
· нс-3 активно поддерживается списком рассылки активных, отзывчивых пользователей, в то время как нс-2 is
незначительно поддерживается и не претерпела значительных изменений в основном дереве кода
на протяжении более десятилетия.
· нс-3 предоставляет функции, недоступные в нс-2, например выполнение кода реализации
среда (позволяющая пользователям запускать реальный код реализации в симуляторе)
· нс-3 обеспечивает более низкий базовый уровень абстракции по сравнению с нс-2, позволяя выровнять
лучше с тем, как устроены настоящие системы. Некоторые ограничения найдены в нс-2 (Такие, как
правильная поддержка нескольких типов интерфейсов на узлах) были исправлены в нс-3.
нс-2 имеет более разнообразный набор добавленных модулей, чем нс-3, благодаря длительному
история. Тем не мение, нс-3 имеет более подробные модели в нескольких популярных областях исследований
(включая сложные модели LTE и WiFi) и его поддержка кода реализации
допускает очень широкий спектр высококачественных моделей. Пользователи могут быть удивлены, узнав, что
весь сетевой стек Linux можно инкапсулировать в нс-3 узел, используя Direct
Фреймворк исполнения кода (DCE). нс-2 модели иногда можно портировать на нс-3, в частности
если они были реализованы на C ++.
Если вы сомневаетесь, хорошим советом будет посмотреть на оба симулятора (а также на другие
симуляторы), и, в частности, модели, доступные для вашего исследования, но имейте в виду
что ваш опыт может быть лучше при использовании инструмента, который активно разрабатывается и
поддерживается (нс-3).
Содействие
нс-3 - это исследовательский и образовательный симулятор, созданный исследовательским сообществом и для него. Так и будет
полагаться на постоянный вклад сообщества в разработку новых моделей, отладку или
поддерживать существующие и делиться результатами. Есть несколько правил, которые, как мы надеемся,
побуждать людей вносить свой вклад в нс-3 как они есть для нс-2:
· Лицензирование с открытым исходным кодом на основе совместимости с GNU GPLv2
· Вики
· Внесенный Code страница, похожая на нс-2популярный добавленный код страница
· Открыть ошибка трекер
Мы понимаем, что если вы читаете этот документ, то участие в проекте будет
возможно, это не ваша главная забота на данный момент, но мы хотим, чтобы вы знали, что
участие в проекте соответствует духу проекта, и даже если вы напишете нам
о вашем раннем опыте с нс-3 (например, "этот раздел руководства был непонятным ..."),
сообщения об устаревшей документации и т. д. приветствуются.
Обучение организация
В учебнике предполагается, что новые пользователи могут сначала пойти по следующему пути:
· Попробуйте скачать и собрать копию;
· Попробуйте запустить несколько примеров программ;
· Посмотрите на результат моделирования и попробуйте его отрегулировать.
В результате мы попытались организовать учебное пособие по вышеуказанным широким последовательностям
Мероприятия.
РЕСУРСЫ
Команда Сайт
Есть несколько важных ресурсов, из которых любой нс-3 пользователь должен знать. Основная сеть
сайт расположен по адресу http://www.nsnam.org и предоставляет доступ к основной информации о
нс-3 система. Подробная документация доступна на главном веб-сайте по адресу
http://www.nsnam.org/documentation/. Вы также можете найти документы, относящиеся к системе
архитектура с этой страницы.
Есть Wiki, дополняющая основной нс-3 веб-сайт, который вы найдете по адресу
http://www.nsnam.org/wiki/. Здесь вы найдете ответы на часто задаваемые вопросы пользователей и разработчиков, а также
руководства по устранению неполадок, сторонний код, документы и т. д.
Исходный код можно найти и просмотреть на http://code.nsnam.org/. Там ты найдешь
текущее дерево разработки в репозитории с именем нс-3-дев. Прошлые выпуски и
Там же можно найти экспериментальные репозитории основных разработчиков.
ртутный
Сложные программные системы нуждаются в каком-либо способе управления организацией и изменениями в
базовый код и документация. Есть много способов совершить этот подвиг, и вы можете
слышали о некоторых системах, которые в настоящее время используются для этого. Параллельный
Система версий (CVS), вероятно, самая известная.
Команда нс-3 проект использует Mercurial в качестве системы управления исходным кодом. Хотя ты не
необходимо много знать о Mercurial, чтобы завершить это руководство, мы рекомендуем
знакомство с Mercurial и его использование для доступа к исходному коду. Mercurial имеет
веб-сайт в http://www.selenic.com/mercurial/, из которого вы можете получить двоичный файл или исходный код
выпуски этой системы управления конфигурацией программного обеспечения (SCM). Selenic (разработчик
из Mercurial) также предоставляет руководство по адресу
http://www.selenic.com/mercurial/wiki/index.cgi/Tutorial/и руководство по быстрому запуску на
http://www.selenic.com/mercurial/wiki/index.cgi/QuickStart/.
Вы также можете найти важную информацию об использовании Mercurial и нс-3 на основной нс-3 Web
сайт.
Waf
После того, как вы загрузили исходный код в вашу локальную систему, вам нужно будет скомпилировать этот
источник для создания полезных программ. Как и в случае с управлением исходным кодом, здесь
доступно множество инструментов для выполнения этой функции. Наверное, самый известный из них
инструменты сделать. Помимо того, что он самый известный, сделать наверное самый сложный
для использования в очень большой и легко настраиваемой системе. Из-за этого много альтернатив
были разработаны. Недавно эти системы были разработаны с использованием Python
язык.
Система сборки Waf используется на нс-3 проект. Это один из нового поколения
Системы сборки на основе Python. Вам не нужно понимать какой-либо Python, чтобы построить
существующий нс-3 системы.
Для тех, кто интересуется кровавыми подробностями о Waf, главный веб-сайт можно найти по адресу
http://code.google.com/p/waf/.
Разработка Окружающая среда
Как упоминалось выше, сценарии в нс-3 выполняется на C ++ или Python. Большинство из нс-3 API есть
доступен на Python, но в любом случае модели написаны на C ++. Рабочий
В этом документе предполагается знание C ++ и объектно-ориентированных концепций. Мы возьмем
некоторое время, чтобы рассмотреть некоторые из более сложных концепций или, возможно, незнакомый язык
функции, идиомы и шаблоны проектирования по мере их появления. Мы не хотим, чтобы это руководство
тем не менее, перейти на учебник по C ++, поэтому мы ожидаем базового владения языком.
Существует почти невообразимое количество источников информации о C ++, доступных на
в Интернете или в печатном виде.
Если вы новичок в C ++, вы можете найти учебник или книгу рецептов или веб-сайт.
и проработайте хотя бы основные функции языка, прежде чем продолжить. Для
экземпляр, этой учебник.
Команда нс-3 Система использует несколько компонентов «инструментальной цепочки» GNU для разработки. А
Программный инструментарий - это набор инструментов программирования, доступных в данной среде. Для
краткий обзор того, что входит в набор инструментов GNU, см.,
http://en.wikipedia.org/wiki/GNU_toolchain. нс-3 использует gcc, GNU binutils и gdb.
Однако мы не используем системные инструменты сборки GNU, ни make, ни autotools. Мы используем Waf
для этих функций.
Обычно нс-3 автор будет работать в Linux или Linux-подобном окружении. Для тех
работает под Windows, существуют среды, которые имитируют среду Linux для
различные степени. В нс-3 проект в прошлом (но не в настоящее время) поддерживал
разработка в среде Cygwin для этих пользователей. Видеть http://www.cygwin.com/ для
подробности о загрузке и посетите нс-3 wiki для получения дополнительной информации о Cygwin и
нс-3. MinGW в настоящее время официально не поддерживается. Другая альтернатива Cygwin -
установить среду виртуальной машины, такую как сервер VMware, и установить виртуальный Linux
машина.
Розетка Программирование
Мы предполагаем, что в примерах, используемых в этом документе, есть базовая возможность с API-интерфейсом Berkeley Sockets.
руководство. Если вы новичок в сокетах, мы рекомендуем ознакомиться с API и некоторыми типами использования.
случаи. Для хорошего обзора программирования сокетов TCP / IP мы рекомендуем TCP / IP Розетки in
C, Донаху и Калверт.
Существует связанный веб-сайт, который включает в себя источник примеров в книге,
вы можете найти по адресу: http://cs.baylor.edu/~donahoo/practical/CSockets/.
Если вы понимаете первые четыре главы книги (или для тех, у кого нет доступа
к копии книги, эхо-клиентам и серверам, показанным на веб-сайте выше), вы будете
быть в хорошей форме, чтобы понять руководство. Есть похожая книга по Multicast
Розетки, Multicast Розетки, Макофске и Альмерот. который охватывает материал, который вам может понадобиться
поймете, если посмотрите примеры многоадресной рассылки в раздаче.
ПОЛУЧЕНИЕ НАЧАЛ
Этот раздел направлен на то, чтобы привести пользователя в рабочее состояние, начиная с машины, которая
возможно никогда не было нс-3 установлены. Он охватывает поддерживаемые платформы, предварительные требования, способы
получать нс-3, способы построения нс-3, а также способы проверки вашей сборки и запуска простых программ.
Обзор
нс-3 построен как система программных библиотек, которые работают вместе. Пользовательские программы могут быть
написано, что связывается с этими библиотеками (или импортируется из них). Пользовательские программы написаны на
языки программирования C ++ или Python.
нс-3 распространяется как исходный код, а это означает, что целевая система должна иметь
среда разработки программного обеспечения, чтобы сначала создать библиотеки, а затем создать пользовательский
программу. нс-3 в принципе могут распространяться в виде встроенных библиотек для избранных
систем, и в будущем он может распространяться таким образом, но в настоящее время многие пользователи
на самом деле делают свою работу, редактируя нс-3 сам, поэтому имея исходный код для восстановления
библиотеки полезны. Если кто-то захочет заняться изготовлением готовых
библиотеки и пакеты для операционных систем, обращайтесь в рассылку ns-developers
.
Далее мы рассмотрим два способа загрузки и создания нс-3, Первый
скачать и собрать официальный релиз с главного веб-сайта. Второй - получить
и создавать копии для разработки нс-3. Мы рассмотрим оба примера, поскольку инструменты
задействованы немного разные.
Загрузка нс-3
Команда нс-3 система в целом представляет собой довольно сложную систему и имеет ряд зависимостей от
другие компоненты. Наряду с системами, с которыми вы, скорее всего, будете иметь дело каждый день (
GNU toolchain, Mercurial, текстовый редактор) вам нужно будет убедиться, что ряд
перед продолжением в вашей системе присутствуют дополнительные библиотеки. нс-3 предоставляет вики
страница, содержащая страницы с множеством полезных советов и подсказок. Одна из таких страниц - это
Страница «Установка», http://www.nsnam.org/wiki/Installation.
В разделе «Предварительные требования» этой вики-страницы объясняется, какие пакеты необходимы для
поддержка общих нс-3 параметры, а также предоставляет команды, используемые для их установки для
распространенные варианты Linux. Пользователи Cygwin должны будут использовать установщик Cygwin (если вы
Пользователь Cygwin, вы использовали его для установки Cygwin).
Вы можете воспользоваться этой возможностью, чтобы изучить нс-3 вики немного, потому что действительно есть
там много информации.
С этого момента мы будем предполагать, что читатель работает в Linux или
Среда эмуляции Linux (Linux, Cygwin и т. Д.) С установленным набором инструментов GNU и
проверяется вместе с предварительными условиями, упомянутыми выше. Мы также предполагаем, что
у вас установлены и работают Mercurial и Waf в целевой системе.
Команда нс-3 код доступен в репозиториях Mercurial на сервере http://code.nsnam.org.
Вы также можете скачать тарбол на http://www.nsnam.org/release/, или ты можешь работать
с репозиториями с использованием Mercurial. Мы рекомендуем использовать Mercurial, если нет хорошего
причина не делать этого. См. В конце этого раздела инструкции о том, как получить архив.
отпустить.
Самый простой способ начать использовать репозитории Mercurial - использовать нс-3-аллинон
среда. Это набор скриптов, который управляет загрузкой и сборкой
различные подсистемы нс-3 для тебя. Мы рекомендуем вам начать свой нс-3 работать в этом
окружающей среды.
Один из способов - создать каталог с именем Рабочее пространство в своем домашнем каталоге, в котором
можно хранить локальные репозитории Mercurial. Подойдет любое имя каталога, но мы предполагаем
который Рабочее пространство здесь используется (примечание: РЕПО также может использоваться в некоторой документации как
пример имени каталога).
Загрузка нс-3 . a тарболл
Tarball - это особый формат программного архива, в котором объединены несколько файлов.
вместе и возможно сжатый архив. нс-3 выпуски программного обеспечения предоставляются через
загружаемый tarball. Процесс загрузки нс-3 через tarball просто; ты только
нужно выбрать выпуск, загрузить и распаковать.
Предположим, вы, как пользователь, хотите создать нс-3 в локальном каталоге под названием
Рабочее пространство. Если вы примете Рабочее пространство каталог, вы можете получить копию релиза
набрав в оболочке Linux следующее (замените соответствующие номера версий,
конечно):
$ cd
Рабочее пространство $ mkdir
$ cd рабочее пространство
$ wget http://www.nsnam.org/release/ns-allinone-3.22.tar.bz2
$ tar xjf ns-allinone-3.22.tar.bz2
Если вы перейдете в каталог нс-аллинон-3.22 вы должны увидеть несколько файлов:
$ лс
запекать constants.py ns-3.22 README
build.py netanim-3.105 pybindgen-0.16.0.886 util.py
Теперь вы готовы построить базу нс-3 распределение.
Загрузка нс-3 . Печь
Bake - это инструмент для распределенной интеграции и сборки, разработанный для нс-3 проект.
Bake можно использовать для получения разрабатываемых версий нс-3 программное обеспечение, а также скачать и
построить пристройки к базе нс-3 распространение, такое как прямое выполнение кода
среда, Network Simulation Cradle, возможность создавать новые привязки Python и другие.
В последнее время нс-3 релизов, Bake включен в архив релизов. Конфигурация
файл, включенный в выпущенную версию, позволит скачать любое программное обеспечение, которое было
тока на момент выпуска. Это, например, версия Bake, которая
распространяется с нс-3.21 релиз можно использовать для получения компонентов для этого нс-3 освободить
или более ранней версии, но не может использоваться для получения компонентов для более поздних выпусков (если только
Bakeconf.xml файл обновлен).
Вы также можете получить самую последнюю копию печь набрав следующее в свой Linux
оболочка (при условии, что вы установили Mercurial):
$ cd
Рабочее пространство $ mkdir
$ cd рабочее пространство
$ hg клон http://code.nsnam.org/bake
При выполнении команды hg (Mercurial) вы должны увидеть что-то вроде следующего
отображается,
...
каталог назначения: запекать
запрос всех изменений
добавление ревизий
добавление манифестов
добавление изменений в файл
добавлено 339 ревизий с 796 изменениями в 63 файла
обновление до ветки по умолчанию
45 файлов обновлено, 0 файлов объединено, 0 файлов удалено, 0 файлов не решено
После завершения команды clone у вас должен быть каталог с именем печь, содержимое
из которых должно выглядеть примерно так:
$ лс
запечь bakeconf.xml doc generate-binary.py TODO
bake.py примеры test
Обратите внимание, что вы действительно только что загрузили несколько сценариев Python и модуль Python с именем
печь. Следующим шагом будет использование этих скриптов для загрузки и сборки нс-3
распределение по вашему выбору.
Доступно несколько целей конфигурации:
1. нс-3.22: модуль, соответствующий выпуску; он загрузит аналогичные компоненты
в архив релиза.
2. нс-3-дев: аналогичный модуль, но с использованием дерева кода разработки
3. нс-аллинон-3.22: модуль, который включает другие дополнительные функции, такие как щелчок
маршрутизация, openflow для нс-3, и подставка для сетевого моделирования
4. нс-3-аллинон: аналогично выпущенной версии модуля allinone, но для
код разработки.
Текущий снимок разработки (не выпущенный) нс-3 можно найти на
http://code.nsnam.org/ns-3-dev/. Разработчики пытаются хранить этот репозиторий в
согласованные, рабочие состояния, но они находятся в области разработки с невыпущенным кодом
присутствует, поэтому вы можете подумать о том, чтобы остаться с официальным выпуском, если вам не нужно
недавно представленные функции.
Вы можете найти последнюю версию кода, просмотрев список репозиториев.
или перейдя в «нс-3 Релизы » веб-страницу и щелкнув ссылку на последний выпуск.
В этом учебном примере мы продолжим работу с нс-3.22.
Теперь мы собираемся использовать инструмент для выпечки, чтобы вытащить различные части нс-3 ты будешь
с использованием. Сначала несколько слов о беговой выпечке.
bake работает, загружая исходные пакеты в исходный каталог и устанавливая
библиотеки в каталог сборки. bake можно запустить, обратившись к двоичному файлу, но если один
выбирает запуск bake из-за пределов каталога, в который он был загружен, рекомендуется
чтобы вставить запекание в свой путь, например, как показано ниже (пример оболочки Linux bash). Во-первых, измените
в каталог 'bake', а затем установите следующие переменные среды
$ export BAKE_HOME = `pwd`
$ export PATH = $ PATH: $ BAKE_HOME: $ BAKE_HOME / build / bin
$ export PYTHONPATH = $ PYTHONPATH: $ BAKE_HOME: $ BAKE_HOME / build / lib
Это поместит программу bake.py в путь оболочки и позволит другим программам
найти исполняемые файлы и библиотеки, созданные bake. Хотя некоторые варианты использования запекания не
требуется установка PATH и PYTHONPATH, как указано выше, полные сборки ns-3-allinone (с
необязательные пакеты) обычно делают.
Войдите в каталог рабочей области и введите в свою оболочку следующее:
$ ./bake.py настроить -e ns-3.22
Далее мы попросим bake проверить, достаточно ли у нас инструментов для загрузки различных компонентов.
Тип:
$ ./bake.py проверить
Вы должны увидеть что-то вроде следующего:
> Python - ОК
> Компилятор GNU C ++ - ОК
> Mercurial - ОК
> CVS - ОК
> GIT - ОК
> Базар - ОК
> Инструмент Tar - ОК
> Инструмент разархивирования - ОК
> Инструмент Unrar - отсутствует
> Утилита сжатия данных 7z - ОК
> Утилита сжатия данных XZ - ОК
> Сделать - ОК
> cMake - ОК
> инструмент заплатки - ОК
> инструмент autoreconf - ОК
> Путь для поиска инструментов: /usr/lib64/qt-3.3/bin / usr / lib64 / ccache
/ USR / местные / бен / бен / USR / бен / usr / местные / sbin / usr / sbin / SBIN
/ дом / том / бен бен
В частности, наши основные инструменты загрузки, такие как Mercurial, CVS, GIT и Bazaar.
проблем на данный момент, поскольку они позволяют нам получить код. Пожалуйста, установите недостающее
инструменты на этом этапе обычным для вашей системы способом (если вы можете), или свяжитесь с
ваш системный администратор по мере необходимости для установки этих инструментов.
Далее попробуйте загрузить программу:
$ ./bake.py скачать
должен дать что-то вроде:
>> Поиск системной зависимости pygoocanvas - ОК
>> Поиск системной зависимости python-dev - ОК
>> Поиск системной зависимости pygraphviz - ОК
>> Скачивание pybindgen-0.16.0.886 - ОК
>> Поиск системной зависимости g ++ - ОК
>> Поиск системной зависимости qt4 - ОК
>> Качаем netanim-3.105 - ОК
>> Качаем нс-3.22 - ОК
Вышесказанное предполагает, что были загружены три источника. Проверить источник каталог
сейчас и введите ls; следует увидеть:
$ лс
нетаним-3.105 нс-3.22 пибиндген-0.16.0.886
Теперь вы готовы построить нс-3 распределение.
Здание нс-3
Здание build.py
При работе из выпущенного архива при первой сборке нс-3 проект вы можете
строить с помощью удобной программы, находящейся в AllInOne каталог. Эта программа называется
build.py. Эта программа настроит для вас проект в наиболее часто используемых
полезный способ. Однако обратите внимание, что более продвинутая настройка и работа с нс-3 предусматривает
обычно включают использование родного нс-3 система сборки Waf, которая будет представлена позже в этом
учебное пособие.
Если вы загрузили с помощью tarball, у вас должен быть каталог с названием что-то вроде
нс-аллинон-3.22 под вашим ~ / рабочая область каталог. Введите следующее:
$ ./build.py --enable-examples --enable-тесты
Поскольку мы работаем с примерами и тестами в этом руководстве, и потому что они не
построен по умолчанию в нс-3, аргументы для build.py говорят ему построить их для нас. В
программа также по умолчанию строит все доступные модули. Позже вы можете построить нс-3
без примеров и тестов, или исключить ненужные для работы модули,
если вы хотите.
Вы увидите множество типичных выходных сообщений компилятора, отображаемых по мере сборки скрипта сборки.
различные части, которые вы скачали. В конце концов вы должны увидеть следующее:
Waf: выход из каталога `/path/to/workspace/ns-allinone-3.22/ns-3.22/build '
'build' успешно завершена (6 мин. 25.032 сек.)
Модули построены:
антенны aodv приложения
конфиг-магазин мостовых зданий
ядро csma csma-layout
dsdv dsr энергии
fd-net-device монитор потока интернет
lr-wpan lte сетка
мобильность mpi netanim (без Python)
Сеть Nix-Vector-Rouing olsr
двухточечное распространение макета точка-точка
статистика спектра sixlowpan
тест на перемычку (без Python) чтение топологии
волна виртуальных сетевых устройств uan
Wi-Fi wimax
Модули не построены (см. Руководство по ns-3 для объяснения):
brite нажмите openflow
визуализатор
Выход из каталога `./ns-3.22 '
Относительно части о не построенных модулях:
Модули не построены (см. Руководство по ns-3 для объяснения):
brite нажмите openflow
визуализатор
Это просто означает, что некоторые нс-3 модули, зависящие от внешних библиотек, не могут
были построены, или что конфигурация специально просила не строить их. Оно делает
не означает, что симулятор не был успешно построен или что он будет работать неправильно.
результаты для модулей, перечисленных как строящиеся.
Здание печь
Если вы использовали bake выше для получения исходного кода из репозиториев проекта, вы можете продолжить
использовать это, чтобы построить нс-3, Тип
Сборка $ ./bake.py
и вы должны увидеть что-то вроде:
>> Сборка pybindgen-0.16.0.886 - ОК
>> Сборка нетаним-3.105 - ОК
>> Корпус нс-3.22 - ОК
Подсказка: причислены выполнять изоферменты печени шаги скачать и строить by требуют 'bake.py развертывать'.
Если произойдет сбой, посмотрите, что сообщает следующая команда
ты; он может указывать на отсутствующую зависимость:
$ ./bake.py показать
В нем будут перечислены различные зависимости пакетов, которые вы пытаетесь собрать.
Здание Waf
До этого момента мы использовали либо build.py сценарий, или печь инструмент, чтобы получить
начал со строительства нс-3. Эти инструменты полезны для создания нс-3 и поддержки
библиотеки, и они звонят в нс-3 каталог для вызова инструмента сборки Waf для выполнения
фактическое здание. Большинство пользователей быстро переходят к использованию Waf напрямую для настройки и
строить нс-3. Итак, чтобы продолжить, смените рабочий каталог на нс-3 каталог
что вы изначально построили.
На данный момент это не обязательно, но будет полезно сделать небольшой объезд
и посмотрите, как внести изменения в конфигурацию проекта. Наверное, самый
полезное изменение конфигурации, которое вы можете сделать, будет заключаться в создании оптимизированной версии
код. По умолчанию вы настроили свой проект на сборку отладочной версии. Скажем
проект для создания оптимизированной сборки. Чтобы объяснить Waf, что он должен быть оптимизирован
сборки, которые включают примеры и тесты, вам нужно будет выполнить следующие
команды:
$. / ваф чистый
$ ./waf --build-profile = optimized --enable-examples --enable-tests configure
Это запускает Waf из локального каталога (что предоставляется для вашего удобства).
Первая команда для очистки предыдущей сборки обычно не является строго необходимой, но
это хорошая практика (но см. Построить Профили, ниже); он удалит ранее построенные
библиотеки и объектные файлы, найденные в каталоге строить/. При перенастройке проекта
и система сборки проверяет различные зависимости, вы должны увидеть результат, который выглядит
аналогично следующему:
Установка сверху на:.
Отправляемся: построить
Проверка на 'gcc' (компилятор c): / usr / bin / gcc
Проверка версии cc: 4.2.1
Проверка на 'g ++' (компилятор c ++): / usr / bin / g ++
Проверка наддува включает: 1_46_1
Проверка буст-библиотек: ок
Проверка сцепления наддува: ок
Проверка местоположения клика: не найдено
Проверка программы pkg-config: / sw / bin / pkg-config
Проверка на 'gtk + -2.0'> = 2.12: да
Проверка на libxml-2.0> = 2.7: да
Проверка типа uint128_t: не найдено
Проверка типа __uint128_t: да
Проверка реализации высокой точности: 128-битное целое число (по умолчанию)
Проверка заголовка stdint.h: да
Проверка заголовка inttypes.h: да
Проверка заголовка sys / inttypes.h: не найдено
Проверка заголовка sys / types.h: да
Проверка заголовка sys / stat.h: да
Проверка заголовка dirent.h: да
Проверка заголовка stdlib.h: да
Проверка заголовка signal.h: да
Проверка заголовка pthread.h: да
Проверка заголовка stdint.h: да
Проверка заголовка inttypes.h: да
Проверка заголовка sys / inttypes.h: не найдено
Проверка библиотеки rt: не найдено
Проверка заголовка netpacket / packet.h: не найдено
Проверка заголовка sys / ioctl.h: да
Проверка заголовка net / if.h: не найдено
Проверка заголовка net / ethernet.h: да
Проверка заголовка linux / if_tun.h: не найдено
Проверка заголовка netpacket / packet.h: не найдено
Проверка местонахождения НБК: не обнаружено
Проверка на "mpic ++": да
Проверка на sqlite3: да
Проверка заголовка linux / if_tun.h: не найдено
Проверка программы sudo: / usr / bin / sudo
Проверка программы valgrind: / sw / bin / valgrind
Проверка на gsl: да
Проверка флага компиляции -Wno-error = deprecated-d ... support: ok
Проверка флага компиляции -Wno-error = deprecated-d ... support: ok
Проверка флага компиляции -fstrict-aliasing ... поддержка: ok
Проверка флага компиляции -fstrict-aliasing ... поддержка: ok
Проверка флага компиляции -Wstrict-aliasing ... поддержка: ok
Проверка флага компиляции -Wstrict-aliasing ... поддержка: ok
Проверка программы doxygen: / usr / local / bin / doxygen
---- Обзор дополнительных функций NS-3:
Профиль сборки: отладка
Каталог сборки: build
Привязки Python: включены
Интеграция BRITE: не включена (BRITE не включена (см. Параметр --with-brite))
Интеграция NS-3 Click: не включена (nsclick не включен (см. Параметр --with-nsclick))
GtkConfigStore: включен
XmlIo: включен
Примитивы потоковой передачи: включены
Симулятор реального времени: включен (librt недоступен)
Эмулированное сетевое устройство: включено ( включить не обнаружено)
Дескриптор файла NetDevice: включен
Нажмите FdNetDevice: не включено (требуется linux / if_tun.h)
Эмуляция FdNetDevice: не включена (требуется netpacket / packet.h)
PlanetLab FdNetDevice: не включен (операционная система PlanetLab не обнаружена (см. Параметр --force-planetlab))
Базовая станция сетевого моделирования: не включена (NSC не найден (см. Параметр --with-nsc))
Поддержка MPI: включена
Интеграция NS-3 OpenFlow: не включена (обязательные библиотеки ускорения не найдены, отсутствуют: система, сигналы, файловая система)
Вывод данных статистики SQlite: включен
Tap Bridge: не включен ( включить не обнаружено)
Визуализатор PyViz: включен
Используйте sudo, чтобы установить бит suid: не включен (опция --enable-sudo не выбрана)
Сборка тестов: включена
Примеры сборки: включено
Научная библиотека GNU (GSL): включена
'configure' успешно завершен (1.944 с)
Обратите внимание на последнюю часть вышеприведенного вывода. Некоторые нс-3 опции не включены по умолчанию или
для правильной работы требуется поддержка базовой системы. Например, чтобы включить
XmlTo, в системе должна быть найдена библиотека libxml-2.0. Если бы этой библиотеки не было
найдены соответствующие нс-3 функция не будет включена, и сообщение будет
отображается. Обратите внимание, что есть возможность использовать программу Sudo установить suid
немного определенных программ. По умолчанию эта функция не включена, поэтому об этой функции сообщается.
как «не включено».
Теперь вернитесь к отладочной сборке, которая включает в себя примеры и тесты.
$. / ваф чистый
$ ./waf --build-profile = debug --enable-examples --enable-tests configure
Теперь система сборки настроена, и вы можете создавать отладочные версии нс-3
программы, просто набрав
$ ./ваф
Ладно, извини, я заставил тебя построить нс-3 часть системы дважды, но теперь вы знаете, как
изменить конфигурацию и построить оптимизированный код.
Рассмотренный выше сценарий build.py поддерживает также --enable-примеры и включить-тесты
аргументы, но, как правило, напрямую не поддерживает другие параметры waf; например, это
не будет работать:
$ ./build.py --отключить-питон
приведет к
build.py: error: нет такой опции: --disable-python
Однако специальный оператор -- может использоваться для передачи дополнительных параметров в waf, поэтому
вместо вышеуказанного будет работать следующее:
$ ./build.py - --disable-python
поскольку он генерирует базовую команду ./ваф конфигурировать --отключить-питон.
Вот еще несколько вводных советов о Waf.
Настроить против Построить
Некоторые команды Waf имеют смысл только на этапе настройки, а некоторые команды
действительно на этапе сборки. Например, если вы хотите использовать функции эмуляции
нс-3, вы можете включить установку бита suid с помощью sudo, как описано выше. Этот
оказывается командой времени конфигурации, поэтому вы можете перенастроить ее с помощью
следующая команда, которая также включает примеры и тесты.
$ ./waf настроить --enable-sudo --enable-examples --enable-tests
Если вы это сделаете, Waf запустит sudo, чтобы изменить программы создания сокетов
код эмуляции для запуска от имени пользователя root.
В Waf доступно множество других параметров настройки и времени сборки. Чтобы изучить эти
варианты, тип:
$ ./ваф --помощь
В следующем разделе мы воспользуемся некоторыми командами, связанными с тестированием.
Построить Профили
Мы уже видели, как настроить Waf для отлаживать or оптимизированный строит:
$ ./waf --build-profile = отладка
Также есть промежуточный профиль сборки, освободить. -d это синоним
--сборка-профиль.
По умолчанию Waf помещает артефакты сборки в строить каталог. Вы можете указать
другой выходной каталог с --из вариант, например
$ ./waf configure --out = foo
Сочетание этого с профилями сборки позволяет переключаться между различными параметрами компиляции.
чистым способом:
$ ./waf configure --build-profile = debug --out = build / debug
Сборка $ ./waf
...
$ ./waf configure --build-profile = optimized --out = build / optimized
Сборка $ ./waf
...
Это позволяет вам работать с несколькими сборками вместо того, чтобы всегда перезаписывать последнюю.
строить. При переключении Waf будет компилировать только то, что нужно, а не перекомпилировать.
все.
Когда вы переключаете профили сборки таким образом, вы должны быть осторожны, чтобы дать то же самое.
параметры конфигурации каждый раз. Может быть удобно определить некоторую среду
переменные, которые помогут избежать ошибок:
$ export NS3CONFIG = "- enable-examples --enable-tests"
$ export NS3DEBUG = "- build-profile = debug --out = build / debug"
$ export NS3OPT == "- build-profile = optimized --out = build / optimized"
$ ./waf настроить $ NS3CONFIG $ NS3DEBUG
Сборка $ ./waf
...
$ ./waf настроить $ NS3CONFIG $ NS3OPT
Сборка $ ./waf
Составители
В приведенных выше примерах Waf использует компилятор GCC C ++, г ++, для строительства нс-3. Тем не менее,
можно изменить компилятор C ++, используемый Waf, указав СХХ охрана окружающей среды
Переменная. Например, чтобы использовать компилятор Clang C ++, лязг ++,
$ CXX = "clang ++" ./waf настроить
Сборка $ ./waf
Также можно настроить Waf для распределенной компиляции с DistCC подобным образом:
$ CXX = "distcc g ++" ./waf configure
Сборка $ ./waf
Дополнительная информация о DistCC и распределенную компиляцию можно найти на нем Проект страница недооценивают ее
Раздел документации.
Установите
Waf можно использовать для установки библиотек в различных местах системы. По умолчанию
место, где создаются библиотеки и исполняемые файлы, находится в строить каталог, и потому что
Waf знает расположение этих библиотек и исполняемых файлов, устанавливать его не нужно.
библиотеки в другом месте.
Если пользователи выбирают установку чего-либо вне каталога сборки, пользователи могут выдавать
./ваф устанавливать команда. По умолчанию префикс для установки / USR / местные, так ./ваф
устанавливать установит программы в / USR / местные / бен, библиотеки в / USR / местные / Библиотекаи
заголовки в / USR / местные / включают. Привилегии суперпользователя обычно требуются для установки на
префикс по умолчанию, поэтому типичная команда будет Sudo ./ваф устанавливать. При беге
программы с Waf, Waf сначала предпочтет использовать разделяемые библиотеки в каталоге сборки,
затем будет искать библиотеки в пути к библиотеке, настроенном в локальной среде. Так
при установке библиотек в систему рекомендуется проверять,
библиотеки используются.
Пользователи могут выбрать установку с другим префиксом, передав --приставка вариант на
настроить время, например:
./waf configure --prefix = / opt / local
Если позже после сборки пользователь выдает ./ваф устанавливать команда, префикс / opt / local
будет использоваться.
Команда ./ваф чистым следует использовать команду до перенастройки проекта, если Waf будет
используется для установки вещей с другим префиксом.
Таким образом, необязательно звонить ./ваф устанавливать использовать нс-3. Большинство пользователей не будут
нужна эта команда, так как Waf заберет текущие библиотеки из строить каталог
но некоторые пользователи могут счесть это полезным, если их вариант использования предполагает работу с программами вне
нс-3 каталог.
один Waf
Есть только один сценарий Waf на верхнем уровне нс-3 исходное дерево. Когда вы работаете, вы
может оказаться, что проводите много времени в царапать/или глубоко в src / ..., и необходимо
вызвать Waf. Вы можете просто вспомнить, где вы находитесь, и вызвать Waf следующим образом:
$ ../../../ваф...
но это утомительно и подвержено ошибкам, и есть лучшие решения.
Если у вас есть полный нс-3 репозиторий эта маленькая жемчужина - начало:
$ cd $ (корень hg) && ./waf ...
Еще лучше определить это как функцию оболочки:
$ function waff {cd $ (корень hg) && ./waf $ *; }
сборка $ waff
Если у вас есть только tarball, вам может помочь переменная окружения:
$ export NS3DIR = "$ PWD"
$ function waff {cd $ NS3DIR && ./waf $ *; }
царапина $ cd
сборка $ waff
Может возникнуть соблазн добавить в каталог модуля тривиальный WAF сценарий по строкам
Exec ../../ваф. Пожалуйста, не надо. Это сбивает с толку новичков, а когда все сделано плохо.
приводит к незаметным ошибкам сборки. Приведенные выше решения - это правильный путь.
Тестирование нс-3
Вы можете запускать модульные тесты нс-3 распространение, запустив ./test.py -c ядро
сценарий:
$ ./test.py -c ядро
Эти тесты выполняются Waf параллельно. В конечном итоге вы должны увидеть отчет, в котором говорится, что
Пройдено 92 из 92 тестов (92 пройдено, 0 не выполнено, 0 вылетело, 0 ошибок valgrind)
Это важное сообщение.
Вы также увидите сводный вывод Waf и средство запуска тестов, выполняющее каждый тест,
что на самом деле будет выглядеть примерно так:
Waf: вход в каталог `/ path / to / workspace / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ path / to / workspace / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (1.799 с)
Модули построены:
мост приложений aodv
нажмите config-store core
csma csma-макет dsdv
монитор потока энергии эму
интернет lte сетка
мобильность mpi netanim
сеть nix-vector-routing ns3tcp
ns3wifi olsr с открытым потоком
двухточечное распространение макета точка-точка
Спектральная статистика ответвитель
инструменты тестирования шаблонов
чтение топологии uan virtual-net-device
визуализатор wi-fi wimax
ПРОЙДЕН: TestSuite ns3-Wi-Fi-интерференция
ПРОЙДЕН: гистограмма TestSuite
...
ПРОЙДЕН: объект TestSuite
ПРОЙДЕН: генераторы случайных чисел TestSuite
Пройдено 92 из 92 тестов (92 пройдено, 0 не выполнено, 0 вылетело, 0 ошибок valgrind)
Эта команда обычно запускается пользователями, чтобы быстро проверить, что нс-3 распространение имеет
построен правильно. (Обратите внимание на порядок ПРОХОДИТЬ: ... линии могут отличаться, и это нормально. Что
важно, чтобы итоговая строка в конце сообщала, что все тесты пройдены; ни один не потерпел неудачу или
разбился.)
Бег a Сценарий
Обычно мы запускаем скрипты под управлением Waf. Это позволяет системе сборки гарантировать
что пути к разделяемым библиотекам заданы правильно и библиотеки доступны по адресу
время выполнения. Чтобы запустить программу, просто используйте --запустить вариант в Waf. Давай запустим нс-3
эквивалент вездесущей программы hello world, набрав следующее:
$ ./waf --запустить привет-симулятор
Waf сначала проверяет правильность сборки программы и выполняет сборку, если
требуется. Затем Waf выполняет программу, которая дает следующий результат.
Привет Симулятор
Поздравляю! Теперь вы пользователь ns-3!
Что do I do if I не посмотреть выход?
Если вы видите сообщения Waf, указывающие, что сборка была успешно завершена, но не
см. вывод "Hello Simulator", есть вероятность, что вы переключили режим сборки на
оптимизированный в Здание Waf раздел, но пропустили изменение обратно на отлаживать Режим.
Весь вывод консоли, используемый в этом руководстве, использует специальный нс-3 компонент регистрации, который
полезен для вывода пользовательских сообщений на консоль. Выход из этого компонента
автоматически отключается при компиляции оптимизированного кода - он «оптимизирован». если ты
не видите вывода «Hello Simulator», введите следующее:
$ ./waf configure --build-profile = debug --enable-examples --enable-tests
чтобы сообщить Waf о создании отладочных версий нс-3 программы, которые включают примеры
и тесты. Вы все равно должны создать актуальную отладочную версию кода, набрав
$ ./ваф
Теперь, если вы запустите привет-симулятор программа, вы должны увидеть ожидаемый результат.
Программа аргументы
Чтобы передать аргументы командной строки в нс-3 программа использует этот шаблон:
$ ./waf --run --command-template = "% s "
Замените название вашей программы на , а аргументы в пользу ,
--шаблон-команды аргумент Waf - это, по сути, рецепт построения фактического
командную строку Waf должен использовать для выполнения программы. Waf проверяет, что сборка
Complete, устанавливает пути к разделяемой библиотеке, затем вызывает исполняемый файл, используя предоставленный
шаблон командной строки, вставив имя программы для %s заполнитель. (Я признаю это
немного неудобно, но так оно и есть. Патчи приветствуются!)
Еще один особенно полезный пример - запуск самого набора тестов. Предположим, что
мой тест набор тестов существует (его нет). Выше мы использовали ./test.py сценарий для запуска всего
множество тестов параллельно, многократно вызывая реальную программу тестирования, испытатель.
Вызывать испытатель непосредственно для одного теста:
$ ./waf --run test-runner --command-template = "% s --suite = mytest --verbose"
Это передает аргументы в испытатель программа. С мой тест не существует,
сообщение об ошибке будет сгенерировано. Распечатать имеющиеся испытатель опции:
$ ./waf --run test-runner --command-template = "% s --help"
Отладка
Бежать нс-3 программы под управлением другой утилиты, например отладчик (или GDB)
или проверка памяти (или Valgrind) вы используете аналогичный --command-template = "..." форме.
Например, чтобы запустить нс-3 программа привет-симулятор с аргументами под
GDB отладчик:
$ ./waf --run = hello-simulator --command-template = "gdb% s --args "
Обратите внимание, что нс-3 название программы идет с --запустить аргумент, а управляющая утилита
(Вот GDB) является первым токеном в --command-шаблон аргумент. В --args говорит GDB
что оставшаяся часть командной строки принадлежит «подчиненной» программе. (Некоторые GDB's
не понимаю --args характерная черта. В этом случае опустите аргументы программы из
--шаблон-команды, и использовать GDB команду набор арг.)
Мы можем объединить этот рецепт и предыдущий, чтобы запустить тест в отладчике:
$ ./waf --run test-runner --command-template = "gdb% s --args --suite = mytest --verbose"
Работы Каталог
Waf необходимо запускать из своего местоположения в верхней части нс-3 дерево. Это становится рабочим
каталог, в который будут записаны выходные файлы. Но что, если вы хотите, чтобы
нс-3 исходное дерево? Использовать --cwd Аргумент:
$ ./waf --cwd = ...
Возможно, будет удобнее начать с вашего рабочего каталога, в котором вы хотите выводить
файлы, и в этом случае может помочь небольшое косвенное обращение:
$ функция waff {
CWD = "$ PWD"
cd $ NS3DIR> / dev / null
./waf --cwd = "$ CWD" $ *
cd -> / dev / null
}
Это украшение предыдущей версии сохраняет текущий рабочий каталог, cdк
каталог Waf, затем инструктирует Waf изменить рабочий каталог назад к спасенным
текущий рабочий каталог перед запуском программы.
КОНЦЕПТУАЛЬНЫЕ О проекте
Первое, что нам нужно сделать, прежде чем начинать смотреть или писать нс-3 код для
объяснить несколько основных концепций и абстракций в системе. Многое из этого может появиться
очевидно, очевидно для некоторых, но мы рекомендуем найти время, чтобы прочитать это
раздел, чтобы убедиться, что вы начинаете на прочном фундаменте.
Основные Абстракции
В этом разделе мы рассмотрим некоторые термины, которые обычно используются в сети, но имеют
конкретное значение в нс-3.
Узел
На интернет-жаргоне вычислительное устройство, которое подключается к сети, называется кашель or
иногда конец система, Потому как нс-3 - это сеть симулятор, а не конкретно
Интернет симулятора, мы намеренно не используем термин "хост", так как он
связанные с Интернетом и его протоколами. Вместо этого мы также используем более общий термин
используется другими симуляторами, которые берут начало в теории графов --- узел.
In нс-3 базовая абстракция вычислительного устройства называется узлом. Эта абстракция
представлен в C ++ классом Узел, Узел класс предоставляет методы для управления
представления вычислительных устройств в симуляциях.
Вы должны подумать о Узел как компьютер, которому вы добавите функциональность. Один добавляет
такие вещи, как приложения, стеки протоколов и периферийные карты с соответствующими
драйверы, позволяющие компьютеру выполнять полезную работу. Мы используем ту же базовую модель в нс-3.
Процесс подачи заявки
Обычно компьютерное программное обеспечение делится на два широких класса. Система ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ организует
различные ресурсы компьютера, такие как память, циклы процессора, диск, сеть и т. д.,
согласно некоторой вычислительной модели. Системное программное обеспечение обычно не использует эти ресурсы
для выполнения задач, которые приносят непосредственную пользу пользователю. Пользователь обычно запускает приложению
который получает и использует ресурсы, контролируемые системным программным обеспечением, для выполнения некоторых
Цель.
Часто разделение системного и прикладного программного обеспечения проводится на
изменение уровня привилегий, которое происходит в ловушках операционной системы. В нс-3 нет настоящего
концепция операционной системы и особенно отсутствие концепции уровней привилегий или системных вызовов.
Однако у нас есть идея приложения. Так же, как программные приложения работают на
компьютеры для выполнения задач в «реальном мире», нс-3 приложения работают на нс-3 Nodes в
моделирование вождения в симулированном мире.
In нс-3 базовая абстракция для пользовательской программы, которая генерирует некоторую деятельность, которая должна быть
смоделировано приложение. Эта абстракция представлена в C ++ классом
Процесс подачи заявки, Процесс подачи заявки класс предоставляет методы для управления представлениями
наша версия приложений пользовательского уровня в моделировании. Ожидается, что разработчики
специализируется на Процесс подачи заявки класс в объектно-ориентированном программировании для создания новых
Приложения. В этом руководстве мы будем использовать специализации класса Процесс подачи заявки под названием
Приложение UdpEchoClient и Приложение UdpEchoServer. Как и следовало ожидать, эти
приложения составляют набор клиент-серверных приложений, используемых для генерации и имитации эха
сетевые пакеты
Канал
В реальном мире компьютер можно подключить к сети. Часто СМИ, над которыми
потоки данных в этих сетях называются каналы. Когда вы подключаете кабель Ethernet к
вилка в стене, вы подключаете свой компьютер к сети Ethernet
канал. В симулированном мире нс-3, один соединяет Узел объекту, представляющему
канал связи. Здесь базовая абстракция коммуникационной подсети называется
канал и представлен в C ++ классом Канал.
Команда Канал класс предоставляет методы для управления объектами подсети связи и
подключение к ним узлов. Каналы также могут быть специализированы разработчиками на объекте
смысл ориентированного программирования. А Канал специализация может моделировать что-то столь же простое, как
провод. Специализированный Канал может также моделировать такие сложные вещи, как большой Ethernet
коммутатор, или трехмерное пространство, полное препятствий в случае беспроводных сетей.
Мы будем использовать специализированные версии Канал под названием CsmaChannel, точка-точка-канал
и Wi-Fiканал в этом руководстве. В CsmaChannel, например, моделирует версию
коммуникационная подсеть, реализующая перевозчик смысл с разными доступ communication
Средняя. Это дает нам функциональность, подобную Ethernet.
Чистыми Устройство
Раньше было так, что если вы хотели подключить компьютеры к сети, вам нужно было
купить сетевой кабель определенного типа и аппаратное устройство, называемое (в терминологии ПК)
периферийный карта который необходимо установить на ваш компьютер. Если периферийная карта
реализовали некоторую сетевую функцию, они назывались сетевыми интерфейсными картами, или сетевые адаптеры.
Сегодня большинство компьютеров поставляются со встроенным оборудованием сетевого интерфейса, и пользователи не видят
эти строительные блоки.
Сетевая карта не будет работать без программного драйвера для управления оборудованием. В Unix (или
Linux), периферийное оборудование классифицируется как устройство. Устройства контролируются
через устройство драйверы, а сетевые устройства (NIC) управляются с помощью сеть устройство
драйверы вместе известный как сеть устройств. В Unix и Linux вы ссылаетесь на эти сети
устройства по таким именам, как eth0.
In нс-3 сеть устройство абстракция охватывает как программный драйвер, так и моделируемый
аппаратное обеспечение. Сетевое устройство «устанавливается» в Узел для того, чтобы включить Узел в
общаться с другими Nodes в моделировании через Каналы. Как и в реальном компьютере,
a Узел может быть подключен к более чем одному Канал через несколько Сетевые устройства.
Абстракция сетевого устройства представлена в C ++ классом NetDevice, NetDevice
класс предоставляет методы для управления подключениями к Узел и Канал объекты; и возможно
специализированный разработчиками в смысле объектно-ориентированного программирования. Мы будем использовать
несколько специализированных версий NetDevice под названием CsmaNetDevice, PointToPointNetDevice,
и WifiNetУстройство в этом руководстве. Так же, как сетевая карта Ethernet предназначена для работы с
Сеть Ethernet, CsmaNetDevice предназначен для работы с CsmaChannel;
PointToPointNetDevice предназначен для работы с точка-точка-канал и еще один Wi-Fi
предназначен для работы с Wi-Fiканал.
Топология Помощники
В реальной сети вы найдете хост-компьютеры с добавленными (или встроенными) сетевыми адаптерами. В нс-3 we
сказал бы, что вы найдете Nodes с прикрепленным Сетевые устройства. В большой моделируемой сети
вам нужно будет организовать много связей между Nodes, Сетевые устройства и Каналы.
С момента подключения Сетевые устройства в Nodes, Сетевые устройства в Каналы, присвоение IP-адресов,
и т. д., являются такими частыми задачами в нс-3, мы предоставляем то, что мы называем топология помощники сделать это
как можно проще. Например, может потребоваться много разных нс-3 основные операции
создать NetDevice, добавить MAC-адрес, установить это сетевое устройство на Узелнастройте
стек протоколов узла, а затем подключите NetDevice к Канал. Еще больше операций
потребуется для подключения нескольких устройств к многоточечным каналам, а затем для подключения
отдельные сети вместе в объединенные сети. Мы предоставляем вспомогательные объекты топологии, которые
объедините эти многочисленные отдельные операции в простую в использовании модель для вашего удобства.
A Имя нс-3 Сценарий
Если вы загрузили систему, как было предложено выше, у вас будет выпуск нс-3 в
каталог называется РЕПО в вашем домашнем каталоге. Перейдите в этот каталог выпуска и
вы должны найти примерно такую структуру каталогов:
АВТОРЫ примеры скретч-утилит waf.bat *
привязки ЛИЦЕНЗИЯ src utils.py waf-tools
построить ns3 test.py * utils.pyc wscript
CHANGES.html README testpy-output ВЕРСИЯ wutils.py
документ RELEASE_NOTES testpy.supp waf * wutils.pyc
Перейти в примеры / учебник каталог. Вы должны увидеть файл с именем первый.cc расположенный
там. Это сценарий, который создаст простую двухточечную связь между двумя узлами.
и передать один пакет между узлами. Давайте посмотрим на эту строку сценария
линия, так что продолжайте и откройте первый.cc в вашем любимом редакторе.
Шаблон
Первая строка в файле - это строка режима emacs. Это сообщает emacs о форматировании
соглашения (стиль кодирования), которые мы используем в нашем исходном коде.
/ * - * - Режим: C ++; c-файл-стиль: "GNU"; indent-tabs-mode: ноль; - * - * /
Это всегда несколько спорная тема, так что мы можем убрать ее с дороги.
немедленно. В нс-3 проект, как и большинство крупных проектов, принял стиль кодирования, чтобы
которого должен придерживаться весь предоставленный код. Если вы хотите внести свой код в
проект, вам в конечном итоге придется соответствовать нс-3 стандарт кодирования, как описано в
файла doc / codingstd.txt или отображается на веб-странице проекта здесь.
Мы рекомендуем вам просто привыкнуть к внешнему виду нс-3 кодировать и принимать
этот стандарт всякий раз, когда вы работаете с нашим кодом. Вся команда разработчиков и
участники сделали это с разным ворчанием. Строка режима emacs выше
упрощает получение правильного форматирования, если вы используете редактор emacs.
Команда нс-3 simulator лицензируется с использованием Стандартной общественной лицензии GNU. Вы увидите
соответствующий юридический язык GNU во главе каждого файла в нс-3 распределение. Часто ты
увидит уведомление об авторских правах для одного из учреждений, участвующих в нс-3 проект выше
текст GPL и автора, указанного ниже.
/*
* Эта программа является бесплатным программным обеспечением; вы можете распространять и / или изменять
* это в соответствии с условиями Стандартной общественной лицензии GNU версии 2 как
* опубликовано Free Software Foundation;
*
* Эта программа распространяется в надежде, что она будет полезной,
* но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; без даже подразумеваемой гарантии
* КОММЕРЧЕСКАЯ ЦЕННОСТЬ или ПРИГОДНОСТЬ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ. Увидеть
* Стандартная общественная лицензия GNU для получения более подробной информации.
*
* Вы должны были получить копию Стандартной общественной лицензии GNU
* вместе с этой программой; если нет, напишите в Бесплатное ПО
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, США
*/
Модули Тур включает:
Собственно код начинается с нескольких операторов include.
#include "ns3 / core-module.h"
#include "ns3 / network-module.h"
#include "ns3 / internet-module.h"
#include "ns3 / point-to-point-module.h"
#include "ns3 / applications-module.h"
Чтобы помочь нашим пользователям сценариев высокого уровня справиться с большим количеством включаемых файлов, присутствующих в
Система, которую мы группируем, включает в себя по относительно большим модулям. Мы предоставляем единый
include-файл, который будет рекурсивно загружать все включаемые файлы, используемые в каждом модуле.
Вместо того, чтобы искать, какой именно заголовок вам нужен, и, возможно, получить
количество зависимостей правильно, мы даем вам возможность загружать группу файлов в большом количестве
детализация. Это не самый эффективный подход, но он, безусловно, заставляет писать
скрипты намного проще.
Каждый из нс-3 включаемые файлы помещаются в каталог с именем ns3 (под сборкой
directory) в процессе сборки, чтобы избежать конфликтов имен включаемых файлов. В
ns3 / core-module.h файл соответствует модулю ns-3, который вы найдете в каталоге
SRC / ядро в загруженном вами дистрибутиве выпуска. Если вы укажете этот каталог, вы
найти большое количество файлов заголовков. Когда вы делаете сборку, Waf размещает публичный заголовок
файлы в ns3 каталог в соответствующем сборка / отладка or сборка / оптимизация каталог
в зависимости от вашей конфигурации. Waf также автоматически сгенерирует модуль include
файл, чтобы загрузить все общедоступные файлы заголовков.
Поскольку вы, конечно, неукоснительно следуете этому руководству, вы уже сделали
a
$ ./waf -d debug --enable-examples --enable-tests настроить
чтобы настроить проект для выполнения отладочных сборок, включающих примеры и тесты.
Вы также сделаете
$ ./ваф
построить проект. Итак, теперь, если вы посмотрите в каталог ../../сборка/отладка/ns3 Вы будете
найдите четыре файла включения модуля, показанные выше. Вы можете ознакомиться с содержанием
эти файлы и обнаруживают, что они включают все общедоступные включаемые файлы в свои
соответствующие модули.
Ns3 Пространство имен
Следующая строка в первый.cc script - это объявление пространства имен.
используя пространство имен ns3;
Команда нс-3 проект реализован в пространстве имен C ++, называемом ns3. Это группирует все
нс-3-связанные объявления в области за пределами глобального пространства имен, что, как мы надеемся, поможет
с интеграцией с другим кодом. C ++ через заявление вводит нс-3 Пространство имен
в текущий (глобальный) декларативный регион. Это причудливый способ сказать, что после
это объявление, вам не нужно будет вводить ns3 :: оператор разрешения области видимости перед всеми
нс-3 код, чтобы использовать его. Если вы не знакомы с пространствами имен, обратитесь к
практически любой учебник по C ++ и сравните ns3 пространство имен и использование здесь с экземплярами
станд пространство имен и через Пространство имен стандарт; заявления, которые вы часто встретите в обсуждениях
of соиЬ и ручьи.
Запись
Следующая строка сценария следующая:
NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
Мы будем использовать это утверждение как удобное место для обсуждения нашей документации Doxygen.
система. Если вы посмотрите на сайт проекта, нс-3 Проект, вы найдете ссылку на
«Документация» на панели навигации. Если вы выберете эту ссылку, вы попадете на наш
страница документации. Ссылка на «Последний выпуск» приведет вас к
документация для последней стабильной версии нс-3. Если вы выберете "API
Документация », вы перейдете на нс-3 Страница документации API.
С левой стороны вы найдете графическое представление структуры
документация. Хорошее место для начала - это NS-3 Модули "книга" в нс-3 навигация
дерево. Если вы расширите Модули вы увидите список нс-3 документация модуля. В
понятие модуля здесь напрямую связано с включенными файлами модуля, описанными выше. В
нс-3 подсистема логирования обсуждается в C + + Формирует (BAPUD) by Все Модули раздел, так что
продолжайте и расширяйте этот узел документации. Теперь разверните Отладка книга, а затем
выберите Запись стр.
Теперь вы должны посмотреть документацию Doxygen для модуля Logging. в
Список #defineвверху страницы вы увидите запись для
NS_LOG_COMPONENT_DEFINE. Прежде чем приступить к делу, возможно, стоит поискать
«Подробное описание» модуля регистрации, чтобы получить представление о работе в целом. Ты
можно прокрутить вниз или выбрать ссылку "Подробнее ..." под диаграммой сотрудничества, чтобы сделать
.
Когда вы получите общее представление о том, что происходит, переходите к конкретному
NS_LOG_COMPONENT_DEFINE документация. Я не буду дублировать здесь документацию, но
Подводя итог, в этой строке объявляется компонент ведения журнала, называемый Пример первого сценария что позволяет
вы можете включать и отключать ведение журнала сообщений консоли по имени.
Главная Функция
Следующие строки скрипта, которые вы найдете, следующие:
Int
main (int argc, char * argv [])
{
Это просто объявление основной функции вашей программы (скрипта). Так же, как в
В любой программе на C ++ необходимо определить основную функцию, которая будет запускаться первой.
Здесь нет ничего особенного. Ваш нс-3 скрипт - это просто программа на C ++.
Следующая строка устанавливает временное разрешение в одну наносекунду, что является значением по умолчанию.
значение:
Время :: SetResolution (Время :: NS);
Разрешение - это наименьшее значение времени, которое может быть представлено (а также наименьшее
представимая разница между двумя значениями времени). Вы можете точно изменить разрешение
однажды. Механизм, обеспечивающий такую гибкость, требует некоторой памяти, поэтому, как только
разрешение было установлено явно, мы освобождаем память, предотвращая дальнейшие обновления.
(Если вы не устанавливаете разрешение явно, по умолчанию оно будет равняться одной наносекунде, а
память будет освобождена, когда начнется симуляция.)
Следующие две строки сценария используются для включения двух компонентов ведения журнала, которые построены
в приложения Echo Client и Echo Server:
LogComponentEnable («UdpEchoClientApplication», LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
Если вы прочитали документацию по компоненту ведения журнала, вы увидите, что там
- это несколько уровней детализации / подробности ведения журнала, которые можно включить для каждого компонента.
Эти две строки кода включают ведение журнала отладки на уровне INFO для эхо-клиентов и
серверы. Это приведет к тому, что приложение будет распечатывать сообщения по мере отправки пакетов.
и получил во время моделирования.
Теперь мы перейдем непосредственно к созданию топологии и запуску моделирования.
Мы используем вспомогательные объекты топологии, чтобы максимально упростить эту работу.
Топология Помощники
Нодконтейнер
Следующие две строки кода в нашем скрипте фактически создадут нс-3 Узел объекты, которые
будет представлять компьютеры в моделировании.
Узлы NodeContainer;
node.Create (2);
Найдем документацию для Нодконтейнер класс, прежде чем мы продолжим. По-другому
попасть в документацию для данного класса можно через Классы вкладка в Doxygen
страниц. Если у вас все еще есть Doxygen, просто прокрутите страницу вверх и
выберите Классы таб. Вы должны увидеть новый набор вкладок, одна из которых Класс
Список. На этой вкладке вы увидите список всех нс-3 классы. Прокрутить вниз,
находясь в поиске ns3 :: NodeContainer. Когда вы найдете класс, выберите его, чтобы перейти к
документация по классу.
Как вы помните, одна из наших ключевых абстракций - это Узел. Это представляет собой компьютер
к которому мы собираемся добавить такие вещи, как стеки протоколов, приложения и периферийные устройства.
открытки. В Нодконтейнер помощник по топологии обеспечивает удобный способ создания, управления и
доступ к любому Узел объекты, которые мы создаем, чтобы запустить симуляцию. Первая строка выше
просто объявляет NodeContainer, который мы называем узлы. Вторая строка вызывает Создавай
метод на узлы объект и просит контейнер создать два узла. Как описано в
Doxygen, контейнер вызывает в нс-3 система, подходящая для создания двух Узел
объекты и хранит указатели на эти объекты внутри.
Узлы в том виде, в котором они представлены в сценарии, ничего не делают. Следующий шаг в построении
топология заключается в соединении наших узлов в сеть. Самый простой вид сети мы
поддержка - это единственная двухточечная связь между двумя узлами. Мы построим один из таких
ссылки здесь.
PointToPointHelper
Мы создаем связь точка-точка, и в схеме, которая станет довольно
знакомый вам, мы используем вспомогательный объект топологии для выполнения низкоуровневой работы, необходимой для размещения
связь вместе. Напомним, что две из наших ключевых абстракций - это NetDevice и
Канал. В реальном мире эти термины примерно соответствуют периферийным картам и
сетевые кабели. Обычно эти две вещи тесно связаны друг с другом, и никто не может
ожидать обмена, например, устройствами Ethernet и беспроводными каналами. Наша топология
Помощники следят за этой интимной связью, и поэтому вы будете использовать один
PointToPointHelper настроить и подключить нс-3 PointToPointNetDevice и
точка-точка-канал объекты в этом скрипте.
Следующие три строки сценария:
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5 Мбит / с"));
pointToPoint.SetChannelAttribute («Задержка», StringValue («2 мс»));
Первая строка,
PointToPointHelper pointToPoint;
создает экземпляр PointToPointHelper объект в стеке. С точки зрения высокого уровня
следующая строка,
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5 Мбит / с"));
сообщает PointToPointHelper объект использовать значение "5 Мбит / с" (пять мегабит в секунду) в качестве
DataRate при создании PointToPointNetDevice объект.
С более подробной точки зрения строка DataRate соответствует тому, что мы называем
Атрибут PointToPointNetDevice. Если вы посмотрите на Doxygen для класса
ns3 :: PointToPointNetDevice и найдите документацию для GetTypeId метод, вы будете
найти список Атрибуты определен для устройства. Среди них DataRate.
Атрибут. Наиболее заметны для пользователей нс-3 объекты имеют аналогичные списки Атрибуты. Мы используем это
механизм для простой настройки моделирования без перекомпиляции, как вы увидите в
следующий раздел.
Подобно "DataRate" на PointToPointNetDevice вы найдете "Задержку" Атрибут
связано с точка-точка-канал. Последняя строка,
pointToPoint.SetChannelAttribute («Задержка», StringValue («2 мс»));
сообщает PointToPointHelper использовать значение "2 мс" (две миллисекунды) в качестве значения
задержка передачи каждого канала точка-точка, которую он впоследствии создает.
NetDeviceContainer
На этом этапе сценария у нас есть Нодконтейнер который содержит два узла. У нас есть
PointToPointHelper что загрунтовано и готово сделать PointToPointNetDevices и провод
точка-точка-канал объекты между ними. Так же, как мы использовали Нодконтейнер топология
вспомогательный объект для создания Nodes для нашей симуляции мы спросим PointToPointHelper
для выполнения работы, связанной с созданием, настройкой и установкой наших устройств для нас. Мы
потребуется список всех созданных объектов NetDevice, поэтому мы используем
NetDeviceContainer для их хранения так же, как мы использовали NodeContainer для хранения узлов, которые мы
созданный. Следующие две строки кода,
Устройства NetDeviceContainer;
devices = pointToPoint.Install (узлы);
завершит настройку устройств и канала. В первой строке объявляется устройство
упомянутый выше контейнер, а второй выполняет тяжелую работу. В Установите метод
PointToPointHelper занимает Нодконтейнер как параметр. Внутри
NetDeviceContainer создано. Для каждого узла в Нодконтейнер (должно быть ровно
два для двухточечного соединения) a PointToPointNetDevice создается и сохраняется на устройстве
контейнер. А точка-точка-канал создается и два PointToPointNetDevices
прикрепил. Когда объекты создаются PointToPointHelper, Атрибуты предварительно
установленные в помощнике используются для инициализации соответствующих Атрибуты в созданном
объекты.
После выполнения pointToPoint.Install (узлы) вызов, у нас будет два узла, каждый с
установленное двухточечное сетевое устройство и единый двухточечный канал между ними.
Оба устройства будут настроены на передачу данных со скоростью пять мегабит в секунду через
канал с задержкой передачи XNUMX миллисекунды.
Интернет-технологии
Теперь у нас есть настроенные узлы и устройства, но у нас нет установленных стеков протоколов.
на наших узлах. Следующие две строки кода позаботятся об этом.
стек InternetStackHelper;
stack.Install (узлы);
Команда Интернет-технологии - помощник по топологии, предназначенный для интернет-стеков.
PointToPointHelper для сетевых устройств точка-точка. В Установите метод занимает
Нодконтейнер как параметр. Когда он будет запущен, он установит Интернет-стек.
(TCP, UDP, IP и т. Д.) На каждом из узлов в контейнере узла.
Ipv4AddressHelper
Затем нам нужно связать устройства на наших узлах с IP-адресами. Мы предоставляем
помощник по топологии для управления выделением IP-адресов. Единственный видимый для пользователя API - это
установить базовый IP-адрес и сетевую маску для использования при выполнении фактического адреса
распределение (которое выполняется на более низком уровне внутри помощника).
Следующие две строки кода в нашем примере сценария, первый.cc,
IPv4AddressHelper адрес;
address.SetBase ("10.1.1.0", "255.255.255.0");
объявить вспомогательный объект адреса и сообщить ему, что он должен начать выделение IP-адресов
из сети 10.1.1.0 с использованием маски 255.255.255.0 для определения назначаемых битов. От
по умолчанию выделенные адреса будут начинаться с единицы и монотонно увеличиваться, поэтому первый
адрес, выделенный из этой базы, будет 10.1.1.1, за которым следует 10.1.1.2 и т. д.
уровень нс-3 система фактически запоминает все выделенные IP-адреса и сгенерирует
фатальная ошибка, если вы случайно дважды сгенерируете один и тот же адрес (что является
кстати, очень сложно отладить ошибку).
Следующая строка кода,
Интерфейсы Ipv4InterfaceContainer = address.Assign (устройства);
выполняет фактическое присвоение адреса. В нс-3 мы делаем связь между IP
адрес и устройство, использующее Ipv4Интерфейс объект. Так же, как иногда нам нужен список
сетевых устройств, созданных помощником для использования в будущем, иногда нам нужен список
Ipv4Интерфейс объекты. В Ipv4InterfaceContainer предоставляет эту функциональность.
Теперь у нас есть построенная двухточечная сеть с установленными стеками и IP-адресами.
назначенный. На данный момент нам нужны приложения для генерации трафика.
Приложения
Еще одна из основных абстракций системы ns-3 - это Процесс подачи заявки. В этом
скрипт мы используем две специализации ядра нс-3 класс Процесс подачи заявки под названием
Приложение UdpEchoServer и Приложение UdpEchoClient. Как и в предыдущем
пояснения, мы используем вспомогательные объекты, чтобы помочь настроить и управлять базовыми объектами.
Здесь мы используем УдпЭхосерверхелпер и УдпЭхоКлиентХелпер предметы, чтобы облегчить нашу жизнь.
УдпЭхосерверхелпер
Следующие строки кода в нашем примере сценария, первый.cc, используются для настройки эха UDP
серверное приложение на одном из ранее созданных узлов.
UdpEchoServerHelper эхосервер (9);
ApplicationContainer serverApps = echoServer.Install(nodes.Get(1));
serverApps.Start (секунды (1.0));
serverApps.Stop (секунды (10.0));
Первая строка кода в приведенном выше фрагменте объявляет УдпЭхосерверхелпер. По-прежнему,
это не само приложение, это объект, который помогает нам создавать настоящие
Приложения. Одна из наших условностей - разместить обязательный Атрибуты в помощнике
конструктор. В этом случае помощник не может сделать ничего полезного, если ему не предоставлен
номер порта, о котором также знает клиент. Вместо того, чтобы просто выбрать один и надеяться
все работает, нам нужен номер порта в качестве параметра конструктора. В
конструктор, в свою очередь, просто выполняет SetAttribute с переданным значением. Если хочешь, ты
можно установить "Порт" Атрибут к другому значению позже, используя SetAttribute.
Подобно многим другим вспомогательным объектам, УдпЭхосерверхелпер объект имеет Установите
метод. Именно выполнение этого метода фактически вызывает базовое эхо
серверное приложение, которое будет создано и присоединено к узлу. Интересно, что Установите
метод занимает NodeContainer как параметр, как и другие Установите методы у нас есть
видимый. Это на самом деле то, что передается методу, хотя это не выглядит так в
Это дело. Есть C ++ безоговорочно Преобразование на работе здесь, которая берет результат
узлов.Получить (1) (который возвращает умный указатель на объект узла --- Ptr) и использует это
в конструкторе для безымянного Нодконтейнер это затем передается Установите. Если вы
когда-либо не мог найти конкретную сигнатуру метода в коде C ++, который компилируется и запускается
просто отлично, ищите такого рода неявные преобразования.
Теперь мы видим, что эхоСервер.Установить собирается установить Приложение UdpEchoServer на
узел найден под номером один из Нодконтейнер мы использовали для управления нашими узлами. Установите
вернет контейнер, содержащий указатели на все приложения (в данном случае одно
так как мы прошли Нодконтейнер содержащий один узел), созданный помощником.
Приложениям требуется время, чтобы "начать" генерировать трафик, и может потребоваться дополнительное время для
"останавливаться". Мы предоставляем и то, и другое. Это время устанавливается с помощью Контейнер приложения методы
Начните и Stop. Эти методы принимают Время параметры. В этом случае мы используем явный C + +
последовательность преобразования, чтобы взять C ++ double 1.0 и преобразовать его в нс-3 Время объект, использующий
a Секунд В ролях. Имейте в виду, что правила преобразования могут контролироваться автором модели,
и C ++ имеет свои собственные правила, поэтому вы не всегда можете просто предположить, что параметры будут счастливы
преобразован для вас. Две строки,
serverApps.Start (секунды (1.0));
serverApps.Stop (секунды (10.0));
заставит приложение эхо-сервера Начните (включить себя) через одну секунду в
моделирование и Stop (отключить себя) через десять секунд после начала симуляции. Благодаря
тот факт, что мы объявили событие моделирования (событие остановки приложения) как
выполняется за десять секунд, симуляция продлится at наименее десять секунд
УдпЭхоКлиентХелпер
Клиентское приложение echo настраивается способом, практически аналогичным методу для
сервер. Есть подспудная Приложение UdpEchoClient которым управляет
УдпЭхоКлиентХелпер.
UdpEchoClientHelper echoClient(interfaces.GetAddress(1), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute («Интервал», TimeValue (секунды (1.0)));
echoClient.SetAttribute ("Размер пакета", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install(nodes.Get(0));
clientApps.Start (секунды (2.0));
clientApps.Stop (секунды (10.0));
Однако для эхо-клиента нам нужно установить пять разных Атрибуты, Первые два
Атрибуты устанавливаются при строительстве УдпЭхоКлиентХелпер. Передаем параметры
которые используются (внутренне для помощника) для установки «RemoteAddress» и «RemotePort»
Атрибуты в соответствии с нашей конвенцией сделать необходимые Атрибуты параметры в
вспомогательные конструкторы.
Напомним, что мы использовали Ipv4InterfaceContainer чтобы отслеживать IP-адреса, которые мы
назначены нашим устройствам. Нулевой интерфейс в интерфейсы контейнер собирается
соответствуют IP-адресу нулевого узла в узлы контейнер. Первое
интерфейс в интерфейсы контейнер соответствует IP-адресу первого узла в
узлы контейнер. Итак, в первой строке кода (сверху) мы создаем
помощник и сообщив ему, что удаленный адрес клиента должен быть IP-адресом.
назначен узлу, на котором находится сервер. Мы также говорим организовать отправку
пакеты на порт девять.
"МаксПакеты" Атрибут сообщает клиенту максимальное количество пакетов, которое мы разрешаем ему
отправить во время моделирования. "Интервал" Атрибут говорит клиенту, как долго ждать
между пакетами и "PacketSize" Атрибут сообщает клиенту, насколько велик его пакет
полезные нагрузки должны быть. С этой конкретной комбинацией Атрибуты, мы говорим
клиент для отправки одного пакета размером 1024 байта.
Как и в случае с эхо-сервером, мы говорим эхо-клиенту, что Начните и Stop, Но
здесь мы запускаем клиента через одну секунду после включения сервера (через две секунды после
моделирование).
Симулятор
Что нам нужно сделать на этом этапе, так это запустить симуляцию. Это делается с помощью
глобальная функция Симулятор :: Беги.
Симулятор :: Беги ();
Когда мы ранее вызывали методы,
serverApps.Start (секунды (1.0));
serverApps.Stop (секунды (10.0));
...
clientApps.Start (секунды (2.0));
clientApps.Stop (секунды (10.0));
мы фактически запланировали события в симуляторе на 1.0 секунды, 2.0 секунды и два события
на 10.0 секунды. Когда Симулятор :: Беги вызывается, система начнет просмотр
список запланированных событий и их выполнение. Сначала он запустит событие через 1.0 секунды,
что позволит приложению эхо-сервера (это событие может, в свою очередь, запланировать многие
другие события). Затем он запустит событие, запланированное на t = 2.0 секунды, которое запустится.
клиентское приложение echo. Опять же, это событие может запланировать еще много событий. Начало
реализация события в клиентском приложении echo начнет фазу передачи данных
симуляция путем отправки пакета на сервер.
Акт отправки пакета на сервер вызовет цепочку событий, которые будут
автоматически запланировано за кулисами и будет выполнять механику
эхо пакета в соответствии с различными параметрами синхронизации, которые мы установили в скрипте.
В конце концов, поскольку мы отправляем только один пакет (вспомните МаксПакетс Атрибут был установлен
one), цепочка событий, запускаемых этим единственным клиентским эхо-запросом, будет сужаться и
симуляция перейдет в режим ожидания. Как только это произойдет, оставшиеся события будут Stop
события для сервера и клиента. Когда эти события выполняются, нет
дальнейшие события для обработки и Симулятор :: Беги возвращается. На этом моделирование завершено.
Осталось только навести порядок. Это делается путем вызова глобальной функции
Симулятор :: Уничтожить. По мере того, как работает помощник (или низкий уровень нс-3 код) выполнены, они
расположил его так, чтобы в симулятор были вставлены крючки для уничтожения всех объектов
которые были созданы. Вам не нужно было следить за этими объектами самостоятельно ---
все, что вам нужно было сделать, это позвонить Симулятор :: Уничтожить и выйти. В нс-3 система позаботилась о
самая сложная часть для вас. Остальные строчки нашего первого нс-3 сценарий, первый.ccпросто делай
, что:
Симулятор :: Уничтожить ();
0 вернуться;
}
После появления имитатор предусматривает останавливаться?
нс-3 представляет собой симулятор дискретного события (DE). В таком симуляторе каждое событие связано
со временем выполнения, и моделирование продолжается путем выполнения событий во временном
порядок времени моделирования. События могут привести к планированию будущих событий (например,
таймер может перепланировать себя, чтобы истечь в следующем интервале).
Начальные события обычно запускаются каждым объектом, например, IPv6 будет планировать маршрутизатор.
Рекламные объявления, запросы соседей и т. Д., Приложение планирует первый пакет
отправка события и т. д.
Когда событие обрабатывается, оно может генерировать ноль, одно или несколько событий. Как симуляция
выполняется, события потребляются, но может (или не может) быть сгенерировано больше событий. В
симуляция остановится автоматически, если в очереди событий больше не будет событий или когда
обнаружено специальное событие Stop. Событие Stop создается через Симулятор :: Стоп
(остановить время); функции.
Типичный случай, когда Симулятор :: Стоп абсолютно необходимо остановить
симуляция: когда есть самоподдерживающееся событие. Самоподдерживающиеся (или повторяющиеся) события
- это события, которые всегда меняются по расписанию. Как следствие, они всегда держат мероприятие
очередь не пуста.
Существует множество протоколов и модулей, содержащих повторяющиеся события, например:
· FlowMonitor - периодическая проверка на потерянные пакеты
· RIPng - периодическая рассылка обновления таблиц маршрутизации
· и т.п.
В этих случаях, Симулятор :: Стоп необходимо, чтобы корректно остановить симуляцию. В
кроме того, когда нс-3 находится в режиме эмуляции, Симулятор реального времени используется для сохранения
часы симуляции согласованы с часами станка, и Симулятор :: Стоп необходимо остановить
процесс.
Многие программы моделирования в руководстве не вызывают явным образом Симулятор :: Стоп,
поскольку в очереди событий автоматически заканчиваются события. Однако эти программы будут
также примите звонок Симулятор :: Стоп. Например, следующий дополнительный оператор в
в первом примере программы будет запланирована явная остановка на 11 секундах:
+ Симулятор :: Стоп (Секунды (11.0));
Симулятор :: Беги ();
Симулятор :: Уничтожить ();
0 вернуться;
}
Вышеупомянутое фактически не изменит поведение этой программы, так как этот конкретный
симуляция естественным образом заканчивается через 10 секунд. Но если бы вы изменили время остановки на
приведенное выше утверждение от 11 секунд до 1 секунды, вы заметите, что симуляция
останавливается до того, как какой-либо вывод будет напечатан на экране (поскольку вывод происходит примерно через 2 секунды).
секунд времени моделирования).
Важно позвонить Симулятор :: Стоп до требуют Симулятор :: Беги; в противном случае,
Симулятор :: Беги никогда не может вернуть управление основной программе для выполнения остановки!
Здание ВАШЕ Сценарий
Мы упростили создание ваших простых скриптов. Все, что вам нужно сделать, это бросить
скрипт в рабочий каталог, и он будет автоматически создан, если вы запустите Waf.
Давай попробуем. Копировать примеры / учебник / first.cc в поцарапать каталог после изменения
обратно в каталог верхнего уровня.
$ кд ../ ..
$ cp examples / tutorial / first.cc scratch / myfirst.cc
Теперь создайте свой первый пример сценария, используя waf:
$ ./ваф
Вы должны увидеть сообщения о том, что ваш мой первый пример построен успешно.
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
[614/708] cxx: scratch / myfirst.cc -> build / debug / scratch / myfirst_3.o
[706/708] cxx_link: сборка / отладка / царапина / myfirst_3.o -> сборка / отладка / царапина / myfirst
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (2.357 с)
Теперь вы можете запустить пример (обратите внимание, что если вы создадите свою программу в рабочем каталоге
вы должны запустить его из рабочего каталога):
$ ./waf - запустить царапину / myfirst
Вы должны увидеть результат:
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.418 с)
Отправлено 1024 байта на 10.1.1.2
Получено 1024 байта с 10.1.1.1
Получено 1024 байта с 10.1.1.2
Здесь вы видите, что система сборки проверяет, был ли файл собран и
затем запускает его. Вы видите, что компонент регистрации на эхо-клиенте указывает, что он отправил
один пакет размером 1024 байта для Echo Server на 10.1.1.2. Вы также видите компонент ведения журнала
на эхо-сервере говорят, что он получил 1024 байта от 10.1.1.1. Эхо-сервер
молча отображает пакет, и вы видите журнал эхо-клиента, что он получил свой пакет
обратно с сервера.
НС-3 Источник Code
Теперь, когда вы использовали некоторые из нс-3 помощники, возможно, вы захотите взглянуть на некоторые из
исходный код, реализующий эту функциональность. Самый последний код можно просмотреть на
наш веб-сервер по следующей ссылке: http://code.nsnam.org/ns-3-dev. Там ты увидишь
страница сводки Mercurial для наших нс-3 дерево развития.
Вверху страницы вы увидите ряд ссылок,
резюме | короткий журнал | журнал изменений | график | теги | файлы
Идите вперед и выберите файлов ссылка на сайт. Это то, что на высшем уровне большинства наших
хранилища будет смотреть:
drwxr-xr-x [вверх]
drwxr-xr-x связывает файлы Python
doc файлы drwxr-xr-x
drwxr-xr-x файлы примеров
drwxr-xr-x ns3 файлы
drwxr-xr-x скретч-файлы
drwxr-xr-x src файлы
drwxr-xr-x файлы утилит
-rw-r - r-- 2009 07:01 +12 47 Файл .hgignore | редакции | аннотировать
-rw-r - r-- 2009 07:01 +12 47 .hgtags файл | редакции | аннотировать
-rw-r - r-- 2009 07:01 +12 47 АВТОРЫ файл | редакции | аннотировать
-rw-r - r-- 2009 07:01 +12 47 Файл CHANGES.html | редакции | аннотировать
-rw-r - r-- 2009 07:01 +12 47 ЛИЦЕНЗИОННЫЙ файл | редакции | аннотировать
-rw-r - r-- 2009 07:01 +12 47 Файл README | редакции | аннотировать
-rw-r - r-- 2009 07:01 +12 47 RELEASE_NOTES файл | редакции | аннотировать
-rw-r - r-- 2009 07:01 +12 47 ВЕРСИЯ файл | редакции | аннотировать
-rwxr-xr-x 2009 07:01 +12 47 waf-файл | редакции | аннотировать
-rwxr-xr-x 2009 07:01 +12 47 файл waf.bat | редакции | аннотировать
-rw-r - r-- 2009 07:01 +12 47 Файл wscript | редакции | аннотировать
-rw-r - r-- 2009 07:01 +12 47 wutils.py file | редакции | аннотировать
Наши примеры скриптов находятся в Примеры реализованных проектов каталог. Если вы нажмете на Примеры реализованных проектов Вы увидите
список подкаталогов. Один из файлов в учебник подкаталог первый.cc. Если вы
нажмите первый.cc вы найдете код, который вы только что прошли.
Исходный код в основном находится в SRC каталог. Вы можете просмотреть исходный код либо по
щелкнув имя каталога или щелкнув файлов ссылка справа от
имя каталога. Если вы нажмете на SRC каталог, вы попадете в список
SRC подкаталоги. Если вы затем нажмете на ядро в подкаталоге вы найдете список
файлы. Первый файл, который вы найдете (на момент написания), это прервать.ч, Если вы нажмете на
прервать.ч ссылка, вам будет отправлен исходный файл для прервать.ч который содержит полезные макросы
для выхода из скриптов при обнаружении ненормальных условий.
Исходный код помощников, которые мы использовали в этой главе, можно найти в
SRC / приложения / помощник каталог. Не стесняйтесь копаться в дереве каталогов, чтобы получить
ощущение того, что есть, и стиль нс-3 программ.
ТВИКИРОВАНИЕ
. Запись Модули
Мы уже вкратце рассмотрели нс-3 модуль регистрации при переходе через
первый.cc сценарий. Теперь мы рассмотрим подробнее и посмотрим, какие варианты использования
подсистема логирования была разработана для покрытия.
Запись Обзор
Многие большие системы поддерживают какие-то средства ведения журнала сообщений, и нс-3 это не
исключение. В некоторых случаях в «консоль оператора» (которая
обычно STDERR в Unix-системах). В других системах предупреждающие сообщения могут быть
вывод, а также более подробные информационные сообщения. В некоторых случаях лесозаготовительные
используются для вывода отладочных сообщений, которые могут быстро превратить вывод в размытие.
нс-3 считает, что все эти уровни детализации полезны, и мы предоставляем
выбираемый многоуровневый подход к регистрации сообщений. Ведение журнала можно полностью отключить,
включается на покомпонентной основе или глобально; и предоставляет возможность выбора
уровни детализации. В нс-3 модуль журнала обеспечивает простой и относительно простой в использовании
способ получить полезную информацию из вашей симуляции.
Вы должны понимать, что мы предоставляем универсальный механизм --- трассировку --- для
получить данные из ваших моделей, которые должны быть предпочтительны для вывода моделирования (см.
раздел учебника Использование системы отслеживания для получения более подробной информации о нашей системе отслеживания).
Ведение журнала должно быть предпочтительным для отладочной информации, предупреждений, сообщений об ошибках или любых других
время, когда вы хотите легко получить быстрое сообщение из ваших скриптов или моделей.
В настоящее время существует семь уровней сообщений журнала увеличивающейся детализации, определенных в
системы.
· LOG_ERROR --- Сообщения об ошибках журнала (связанный макрос: NS_LOG_ERROR);
· LOG_WARN --- Записывать предупреждающие сообщения (связанный макрос: NS_LOG_WARN);
· LOG_DEBUG --- Регистрировать относительно редкие, специальные сообщения отладки (связанный макрос:
NS_LOG_DEBUG);
· LOG_INFO --- Записывать информационные сообщения о ходе выполнения программы (связанный макрос:
NS_LOG_INFO);
· LOG_FUNCTION --- Записывать сообщение, описывающее каждую вызываемую функцию (два связанных макроса:
NS_LOG_FUNCTION, используемый для функций-членов, и NS_LOG_FUNCTION_NOARGS, используемый для статических
функции);
· LOG_LOGIC - сообщения журнала, описывающие логический поток в функции (связанный макрос:
NS_LOG_LOGIC);
· LOG_ALL --- Записывать все, что упомянуто выше (без связанного макроса).
Для каждого LOG_TYPE существует также LOG_LEVEL_TYPE, который, если он используется, позволяет регистрировать все
уровни над ним в дополнение к его уровню. (Как следствие этого LOG_ERROR и
LOG_LEVEL_ERROR, а также LOG_ALL и LOG_LEVEL_ALL функционально эквивалентны.) Для
Например, включение LOG_INFO включит только сообщения, предоставленные макросом NS_LOG_INFO, в то время как
включение LOG_LEVEL_INFO также включит сообщения, предоставляемые NS_LOG_DEBUG, NS_LOG_WARN
и макросы NS_LOG_ERROR.
Мы также предоставляем макрос безусловной регистрации, который всегда отображается независимо от
уровни ведения журнала или выбор компонентов.
· NS_LOG_UNCOND - Безоговорочно записывать связанное сообщение (без связанного уровня журнала).
Каждый уровень можно запросить отдельно или в совокупности; и ведение журнала можно настроить с помощью
переменная среды оболочки (NS_LOG) или путем регистрации вызова системной функции. Как было видно
ранее в руководстве система ведения журналов имеет документацию Doxygen, и теперь она будет
Хорошее время для ознакомления с документацией модуля ведения журнала, если вы еще этого не сделали.
Теперь, когда вы очень подробно прочитали документацию, давайте воспользуемся некоторыми из этих знаний.
получить интересную информацию из царапина / myfirst.cc пример сценария у вас есть
уже построен.
Включение Запись
Давайте воспользуемся переменной окружения NS_LOG, чтобы включить еще немного журнала, но сначала просто чтобы
сориентироваться, запустить последний скрипт так же, как и раньше,
$ ./waf - запустить царапину / myfirst
Вы должны увидеть уже знакомый результат первого нс-3 пример программы
$ Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.413 с)
Отправлено 1024 байта на 10.1.1.2
Получено 1024 байта с 10.1.1.1
Получено 1024 байта с 10.1.1.2
Оказывается, что сообщения "Отправлено" и "Получено", которые вы видите выше, на самом деле регистрируются
сообщения от Приложение UdpEchoClient и Приложение UdpEchoServer. Мы можем спросить
клиентское приложение, например, чтобы распечатать дополнительную информацию, установив уровень ведения журнала
через переменную окружения NS_LOG.
Я собираюсь предположить, что вы используете оболочку, подобную sh, которая использует
синтаксис "ПЕРЕМЕННАЯ = значение". Если вы используете оболочку, подобную csh, вам придется
преобразовать мои примеры в синтаксис "setenv VARIABLE value", требуемый этими оболочками.
Прямо сейчас клиентское приложение эха UDP отвечает на следующую строку кода в
царапина / myfirst.cc,
LogComponentEnable («UdpEchoClientApplication», LOG_LEVEL_INFO);
Эта строка кода позволяет LOG_LEVEL_INFO уровень ведения журнала. Когда мы проходим регистрацию
флаг уровня, мы фактически включаем данный уровень и все более низкие уровни. В таком случае,
мы включили NS_LOG_INFO, NS_LOG_DEBUG, NS_LOG_WARN и NS_LOG_ERROR. Мы можем увеличить
уровень ведения журнала и получить дополнительную информацию без изменения сценария и перекомпиляции с помощью
установка переменной окружения NS_LOG следующим образом:
$ export NS_LOG = UdpEchoClientApplication = level_all
Это устанавливает переменную среды оболочки НС_ЛОГ к строке,
UdpEchoClientApplication = level_all
Левая часть назначения - это имя компонента ведения журнала, который мы хотим установить,
а правая часть - это флаг, который мы хотим использовать. В этом случае мы собираемся включить
все уровни отладки для приложения. Если вы запускаете скрипт с установленным NS_LOG
таким образом, нс-3 система регистрации зафиксирует изменение, и вы должны увидеть следующее
вывод:
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.404 с)
UdpEchoClientApplication: UdpEchoClient ()
Приложение UdpEchoClient:SetDataSize(1024)
UdpEchoClientApplication: StartApplication ()
UdpEchoClientApplication: ScheduleTransmit ()
UdpEchoClientApplication: Отправить ()
Отправлено 1024 байта на 10.1.1.2
Получено 1024 байта с 10.1.1.1
UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
Получено 1024 байта с 10.1.1.2
UdpEchoClientApplication: StopApplication ()
UdpEchoClientApplication: DoDispose ()
UdpEchoClientApplication: ~ UdpEchoClient ()
Дополнительная отладочная информация, предоставляемая приложением, взята из NS_LOG_FUNCTION
уровень. Это отображается каждый раз, когда функция в приложении вызывается во время скрипта.
исполнение. Как правило, использование (как минимум) NS_LOG_FUNCTION (this) в функциях-членах является
предпочтительнее. Используйте NS_LOG_FUNCTION_NOARGS () только в статических функциях. Обратите внимание, однако, что
в нс-3 система, модели которой должны поддерживать какую-либо конкретную
функция ведения журнала. Решение о том, сколько информации регистрируется, остается на усмотрение
индивидуальный разработчик модели. В случае приложений эхо большой объем журнала
вывод доступен.
Теперь вы можете увидеть журнал вызовов функций, которые были выполнены в приложении. если ты
присмотритесь, вы заметите двоеточие между строкой Приложение UdpEchoClient
и имя метода, в котором вы могли ожидать оператор области видимости C ++ (::). Это
умышленно.
Имя на самом деле не является именем класса, это имя компонента ведения журнала. Когда есть
взаимно однозначное соответствие между исходным файлом и классом, обычно это
имя класса, но вы должны понимать, что на самом деле это не имя класса, и есть
одинарное двоеточие вместо двойного двоеточия, чтобы относительно тонко напомнить вам
концептуально отделите имя компонента ведения журнала от имени класса.
Оказывается, в некоторых случаях бывает сложно определить, какой метод на самом деле
генерирует сообщение журнала. Если вы посмотрите текст выше, вы можете спросить, где строка
"Полученный 1024 байт от 10.1.1.2"исходит от. Вы можете решить эту проблему, выбрав ИЛИ
prefix_func уровень в НС_ЛОГ переменная окружения. Попробуйте сделать следующее,
$ export 'NS_LOG = UdpEchoClientApplication = level_all | prefix_func'
Обратите внимание, что кавычки необходимы, поскольку вертикальная черта, которую мы используем для обозначения ИЛИ
операция также является соединителем каналов Unix.
Теперь, если вы запустите сценарий, вы увидите, что система ведения журнала гарантирует, что каждый
сообщение от данного компонента журнала имеет префикс с именем компонента.
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.417 с)
UdpEchoClientApplication: UdpEchoClient ()
Приложение UdpEchoClient:SetDataSize(1024)
UdpEchoClientApplication: StartApplication ()
UdpEchoClientApplication: ScheduleTransmit ()
UdpEchoClientApplication: Отправить ()
UdpEchoClientApplication: Send (): отправлено 1024 байта в 10.1.1.2
Получено 1024 байта с 10.1.1.1
UdpEchoClientApplication:HandleRead(0x6241e0, 0x624a20)
UdpEchoClientApplication: HandleRead (): получено 1024 байта из 10.1.1.2
UdpEchoClientApplication: StopApplication ()
UdpEchoClientApplication: DoDispose ()
UdpEchoClientApplication: ~ UdpEchoClient ()
Теперь вы можете видеть, что все сообщения, поступающие из клиентского приложения UDP echo, являются
определены как таковые. Сообщение «Получено 1024 байта из 10.1.1.2» теперь четко
определяется как исходящий от клиентского приложения эхо. Оставшееся сообщение должно быть
поступает из приложения эхо-сервера UDP. Мы можем включить этот компонент, введя
Список компонентов в переменной окружения NS_LOG, разделенных двоеточиями.
$ export 'NS_LOG = UdpEchoClientApplication = level_all | prefix_func:
UdpEchoServerApplication = level_all | prefix_func '
Предупреждение: вам нужно будет удалить новую строку после : в примере текста выше которого
существует только для целей форматирования документа.
Теперь, если вы запустите сценарий, вы увидите все сообщения журнала как от клиента echo
и серверные приложения. Вы можете увидеть, что это может быть очень полезно при отладке проблем.
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.406 с)
UdpEchoServerApplication: UdpEchoServer ()
UdpEchoClientApplication: UdpEchoClient ()
Приложение UdpEchoClient:SetDataSize(1024)
UdpEchoServerApplication: StartApplication ()
UdpEchoClientApplication: StartApplication ()
UdpEchoClientApplication: ScheduleTransmit ()
UdpEchoClientApplication: Отправить ()
UdpEchoClientApplication: Send (): отправлено 1024 байта в 10.1.1.2
UdpEchoServerApplication: HandleRead (): получено 1024 байта из 10.1.1.1
UdpEchoServerApplication: HandleRead (): эхо-пакет
UdpEchoClientApplication: HandleRead (0x624920, 0x625160)
UdpEchoClientApplication: HandleRead (): получено 1024 байта из 10.1.1.2
UdpEchoServerApplication: StopApplication ()
UdpEchoClientApplication: StopApplication ()
UdpEchoClientApplication: DoDispose ()
UdpEchoServerApplication: DoDispose ()
UdpEchoClientApplication: ~ UdpEchoClient ()
UdpEchoServerApplication: ~ UdpEchoServer ()
Также иногда полезно иметь возможность увидеть время моделирования, в которое сообщение журнала
генерируется. Вы можете сделать это с помощью ИЛИ в бите prefix_time.
$ export 'NS_LOG = UdpEchoClientApplication = level_all | prefix_func | prefix_time:
UdpEchoServerApplication = level_all | prefix_func | prefix_time '
Опять же, вам придется удалить указанную выше новую строку. Если вы запустите сценарий сейчас, вы должны
см. следующий вывод:
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.418 с)
0s UdpEchoServerApplication: UdpEchoServer ()
0s UdpEchoClientApplication: UdpEchoClient ()
0s Приложение UdpEchoClient:SetDataSize(1024)
1с UdpEchoServerApplication: StartApplication ()
2s UdpEchoClientApplication: StartApplication ()
2s UdpEchoClientApplication: ScheduleTransmit ()
2s UdpEchoClientApplication: Send ()
2s UdpEchoClientApplication: Send (): отправлено 1024 байта на адрес 10.1.1.2
2.00369. 1024s UdpEchoServerApplication: HandleRead (): получено 10.1.1.1 байта от XNUMX
2.00369. XNUMXs UdpEchoServerApplication: HandleRead (): эхо-пакет
2.00737s UdpEchoClientApplication:HandleRead(0x624290, 0x624ad0)
2.00737. 1024s UdpEchoClientApplication: HandleRead (): получено 10.1.1.2 байта от XNUMX
10 с. UdpEchoServerApplication: StopApplication ()
10 с. UdpEchoClientApplication: StopApplication ()
UdpEchoClientApplication: DoDispose ()
UdpEchoServerApplication: DoDispose ()
UdpEchoClientApplication: ~ UdpEchoClient ()
UdpEchoServerApplication: ~ UdpEchoServer ()
Вы можете видеть, что конструктор UdpEchoServer был вызван во время моделирования
0 секунд. На самом деле это происходит до начала моделирования, но время
отображается как ноль секунд. То же верно и для сообщения конструктора UdpEchoClient.
Напомним, что царапина / first.cc скрипт запустил приложение эхо-сервера за одну секунду
в моделирование. Теперь вы можете видеть, что Запустить приложение метод сервера,
собственно, позвонили за одну секунду. Вы также можете видеть, что клиентское приложение echo
запускается при времени моделирования в две секунды, как мы и просили в сценарии.
Теперь вы можете следить за ходом симуляции из РасписаниеПередача позвонить в
клиент, который звонит Отправьте до РучкаЧитать обратный вызов в приложении эхо-сервера. Примечание
что истекшее время для отправки пакета по каналу точка-точка составляет 3.69
миллисекунды. Вы видите, что эхо-сервер регистрирует сообщение о том, что он эхо
пакет, а затем, после другой задержки канала, вы видите, что эхо-клиент получает
эхом отозвался пакет в своем РучкаЧитать метод.
В этой симуляции многое происходит под прикрытием, и вы не являетесь
видя также. Вы можете очень легко следить за всем процессом, включив все
компоненты журнала в системе. Попробуйте установить НС_ЛОГ переменная к следующему,
$ export 'NS_LOG = * = level_all | prefix_func | prefix_time'
Звездочка выше - это подстановочный знак компонента ведения журнала. Это включит все
регистрация всех компонентов, используемых в моделировании. Я не буду воспроизводить вывод
здесь (на момент написания он производит 1265 строк вывода для одиночного эхо-сигнала пакета), но
вы можете перенаправить эту информацию в файл и просматривать его в своем любимом
редактор, если хотите,
$ ./waf --run scratch / myfirst> log.out 2> & 1
Я лично использую эту чрезвычайно подробную версию ведения журнала, когда мне предоставляют
проблема, и я понятия не имею, где что-то идет не так. Я могу следить за прогрессом
код довольно легко, без необходимости устанавливать точки останова и выполнять код в отладчике.
Я могу просто отредактировать вывод в моем любимом редакторе и поискать то, что я ожидаю,
и вижу, что происходит, чего я не ожидал. Когда у меня есть общее представление о том, что
если что-то пошло не так, я перехожу в отладчик для детального изучения проблемы.
Такой вывод может быть особенно полезен, когда ваш скрипт что-то полностью выполняет.
непредвиденный. Если вы пошагово используете отладчик, вы можете пропустить неожиданную экскурсию.
полностью. Запись экскурсии делает ее быстро видимой.
Добавление Запись в Code
Вы можете добавить новое ведение журнала к своим симуляциям, выполнив вызовы компонента журнала через
несколько макросов. Сделаем это в мой первый.cc сценарий у нас есть в поцарапать каталог.
Напомним, что в этом скрипте мы определили компонент ведения журнала:
NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
Теперь вы знаете, что можете включить все ведение журнала для этого компонента, установив параметр
НС_ЛОГ переменная окружения на различных уровнях. Давайте продолжим и добавим логирование в
сценарий. Макрос, используемый для добавления сообщения журнала информационного уровня: NS_LOG_INFO, Идти
впереди и добавьте один (непосредственно перед тем, как мы начнем создавать узлы), который сообщает вам, что сценарий
это «Создание топологии». Это делается, как в этом фрагменте кода,
Откройте царапина / myfirst.cc в вашем любимом редакторе и добавьте строчку,
NS_LOG_INFO («Создание топологии»);
прямо перед строками,
Узлы NodeContainer;
node.Create (2);
Теперь создайте скрипт с помощью waf и очистите НС_ЛОГ переменная, чтобы отключить торрент
ведение журнала, которое мы ранее включили:
$ ./ваф
$ экспорт NS_LOG =
Теперь, если вы запустите сценарий,
$ ./waf - запустить царапину / myfirst
Вы будете увидеть ваше новое сообщение с момента связанного с ним компонента ведения журнала
(Пример первого сценария) не был включен. Чтобы увидеть ваше сообщение, вам нужно будет
разрешить Пример первого сценария компонент ведения журнала с уровнем выше или равным
NS_LOG_INFO. Если вы просто хотите увидеть этот конкретный уровень ведения журнала, вы можете включить его
от,
$ export NS_LOG = FirstScriptExample = информация
Если вы сейчас запустите сценарий, вы увидите новое сообщение журнала «Создание топологии»,
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.404 с)
Создание топологии
Отправлено 1024 байта на 10.1.1.2
Получено 1024 байта с 10.1.1.1
Получено 1024 байта с 10.1.1.2
. Command линия аргументы
Переопределение По умолчанию Атрибуты
Другой способ изменить то, как нс-3 сценарии работают без редактирования, а сборка осуществляется через
команду линия аргументы. Мы предоставляем механизм для анализа аргументов командной строки и
автоматически устанавливать локальные и глобальные переменные на основе этих аргументов.
Первым шагом в использовании системы аргументов командной строки является объявление командной строки
парсер. Это делается довольно просто (в вашей основной программе), как в следующем коде,
Int
main (int argc, char * argv [])
{
...
Командная строка командной строки;
cmd.Parse(argc, argv);
...
}
Этот простой двухстрочный фрагмент на самом деле очень полезен сам по себе. Он открывает дверь в
нс-3 глобальная переменная и Атрибут системы. Идите вперед и добавьте эти две строки кода в
царапина / myfirst.cc сценарий в начале main. Создайте сценарий и запустите
это, но попросите скрипт о помощи следующим образом:
$ ./waf - выполнить "scratch / myfirst --PrintHelp"
Это попросит Waf запустить царапина / мой первый скрипт и передайте аргумент командной строки
--Печать к сценарию. Цитаты необходимы, чтобы разобраться, какая программа получает какие
аргумент. Теперь синтаксический анализатор командной строки увидит --Печать аргументировать и отвечать,
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.413 с)
TcpL4Protocol: TcpStateMachine ()
CommandLine: HandleArgument (): Обработать имя аргумента = значение PrintHelp =
--PrintHelp: распечатать это справочное сообщение.
--PrintGroups: распечатать список групп.
--PrintTypeIds: распечатать все TypeIds.
--PrintGroup = [группа]: распечатать все идентификаторы типа группы.
--PrintAttributes = [typeid]: распечатать все атрибуты typeid.
--PrintGlobals: распечатать список глобальных объектов.
Давайте сосредоточимся на --PrintAttributes вариант. Мы уже намекали на нс-3 Атрибут
система во время прогулки по первый.cc сценарий. Мы рассмотрели следующие строки
код,
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5 Мбит / с"));
pointToPoint.SetChannelAttribute («Задержка», StringValue («2 мс»));
и упомянул, что Скорость передачи данных на самом деле был Атрибут PointToPointNetDevice. Давайте
используйте синтаксический анализатор аргументов командной строки, чтобы взглянуть на Атрибуты
PointToPointNetDevice. В справочном листе говорится, что мы должны предоставить Идентификатор типа. Это
соответствует имени класса того класса, к которому Атрибуты принадлежать. В таком случае
это будет ns3 :: PointToPointNetDevice. Давайте продолжим и введите,
$ ./waf --run "scratch / myfirst --PrintAttributes = ns3 :: PointToPointNetDevice"
Система распечатает все Атрибуты такого сетевого устройства. Среди
Атрибуты вы увидите, что в списке есть,
--ns3 :: PointToPointNetDevice :: DataRate = [32768 бит / с]:
Скорость передачи данных по умолчанию для двухточечных ссылок
Это значение по умолчанию, которое будет использоваться, когда PointToPointNetDevice создается в
система. Мы отменили это значение по умолчанию с помощью Атрибут установка в PointToPointHelper
выше. Давайте использовать значения по умолчанию для двухточечных устройств и каналов по
удаление SetDeviceAttribute звонок и Сетканалатрибуте звонок из мой первый.cc
у нас есть в рабочем каталоге.
Теперь ваш сценарий должен просто объявить PointToPointHelper и не делать никаких набор операции
как в следующем примере,
...
Узлы NodeContainer;
node.Create (2);
PointToPointHelper pointToPoint;
Устройства NetDeviceContainer;
devices = pointToPoint.Install (узлы);
...
Идите вперед и создайте новый скрипт с помощью Waf (./ваф) и давайте вернемся и включим некоторые
ведение журнала из приложения эхо-сервера UDP и включение временного префикса.
$ export 'NS_LOG = UdpEchoServerApplication = level_all | prefix_time'
Если вы запустите сценарий, вы должны увидеть следующий результат:
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.405 с)
0s UdpEchoServerApplication: UdpEchoServer ()
1с UdpEchoServerApplication: StartApplication ()
Отправлено 1024 байта на 10.1.1.2
2.25732s Получено 1024 байта от 10.1.1.1
2.25732 с. Эхо-пакет
Получено 1024 байта с 10.1.1.2
10 с. UdpEchoServerApplication: StopApplication ()
UdpEchoServerApplication: DoDispose ()
UdpEchoServerApplication: ~ UdpEchoServer ()
Напомним, что в прошлый раз мы смотрели на время моделирования, когда пакет был
полученное эхо-сервером, оно составило 2.00369 секунды.
2.00369. 1024s UdpEchoServerApplication: HandleRead (): получено 10.1.1.1 байта от XNUMX
Теперь он получает пакет за 2.25732 секунды. Это потому, что мы только что сбросили
скорость передачи данных PointToPointNetDevice до значения по умолчанию 32768 бит в секунду с
пять мегабит в секунду.
Если бы мы предоставили новый Скорость передачи данных используя командную строку, мы могли ускорить нашу симуляцию
снова вверх. Делаем это следующим образом, по формуле, подразумеваемой в справке.
пункт:
$ ./waf --run "scratch / myfirst --ns3 :: PointToPointNetDevice :: DataRate = 5 Мбит / с"
Это установит значение по умолчанию для Скорость передачи данных Атрибут обратно к пяти мегабитам на
второй. Вы удивлены результатом? Оказывается, чтобы получить оригинал
поведение скрипта обратно, нам нужно будет установить задержку скорости света канала
также. Мы можем попросить систему командной строки распечатать Атрибуты канала
точно так же, как мы сделали для сетевого устройства:
$ ./waf --run "scratch / myfirst --PrintAttributes = ns3 :: PointToPointChannel"
Мы открываем задержка Атрибут канала задается следующим образом:
--ns3 :: PointToPointChannel :: Delay = [0ns]:
Задержка передачи по каналу
Затем мы можем установить оба этих значения по умолчанию через систему командной строки,
$ ./waf --run "царапина / myfirst
--ns3 :: PointToPointNetDevice :: DataRate = 5 Мбит / с
--ns3 :: PointToPointChannel :: Delay = 2 мс "
в этом случае мы восстанавливаем время, которое у нас было, когда мы явно устанавливали Скорость передачи данных и задержка
в скрипте:
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.417 с)
0s UdpEchoServerApplication: UdpEchoServer ()
1с UdpEchoServerApplication: StartApplication ()
Отправлено 1024 байта на 10.1.1.2
2.00369s Получено 1024 байта от 10.1.1.1
2.00369 с. Эхо-пакет
Получено 1024 байта с 10.1.1.2
10 с. UdpEchoServerApplication: StopApplication ()
UdpEchoServerApplication: DoDispose ()
UdpEchoServerApplication: ~ UdpEchoServer ()
Обратите внимание, что пакет снова принимается сервером в 2.00369 секунды. Мы могли бы
фактически установить любой из Атрибуты используется в сценарии таким образом. В частности, мы могли
установите УдпЭхоКлиент Атрибут МаксПакетс к какому-то другому значению, кроме одного.
Как бы вы это сделали? Попробуйте. Помните, вы должны прокомментировать это место
мы отменяем значение по умолчанию Атрибут и явно установить МаксПакетс в сценарии. Затем вы
придется пересобирать скрипт. Вам также нужно будет найти синтаксис для фактической установки
новое значение атрибута по умолчанию с помощью средства справки командной строки. Как только у вас будет это
выяснил, что вы должны иметь возможность контролировать количество пакетов, отраженных от команды
линия. Поскольку мы хорошие люди, мы скажем вам, что ваша командная строка должна выглядеть
что-то вроде,
$ ./waf --run "царапина / myfirst
--ns3 :: PointToPointNetDevice :: DataRate = 5 Мбит / с
--ns3 :: PointToPointChannel :: Delay = 2 мс
--ns3 :: UdpEchoClient :: MaxPackets = 2 "
Зацепление ВАШЕ Собственный Наши ценности
Вы также можете добавить свои собственные хуки в систему командной строки. Это делается довольно просто
используя Добавить значение в синтаксический анализатор командной строки.
Давайте воспользуемся этой возможностью, чтобы указать количество пакетов для эха в совершенно другом
способ. Добавим локальную переменную с именем нПакеты до main функция. Мы инициализируем
его к одному, чтобы соответствовать нашему предыдущему поведению по умолчанию. Чтобы разрешить синтаксическому анализатору командной строки
измените это значение, нам нужно подключить значение к парсеру. Мы делаем это, добавляя звонок
в Добавить значение. Идите вперед и измените царапина / myfirst.cc сценарий, чтобы начать с
следующий код,
Int
main (int argc, char * argv [])
{
uint32_t нпакетов = 1;
Командная строка командной строки;
cmd.AddValue ("nPackets", "Количество пакетов для эха", nPackets);
cmd.Parse(argc, argv);
...
Прокрутите вниз до того места в скрипте, где мы установили МаксПакетс Атрибут и изменить это
так что он установлен в переменную нПакеты вместо постоянного 1 как показано ниже.
echoClient.SetAttribute ("MaxPackets", UintegerValue (nPackets));
Теперь, если вы запустите сценарий и предоставите --Печать аргумент, вы должны увидеть свой новый
Информация о пользователе Аргумент перечислены на экране справки.
Пытаться,
$ ./waf - выполнить "scratch / myfirst --PrintHelp"
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.403 с)
--PrintHelp: распечатать это справочное сообщение.
--PrintGroups: распечатать список групп.
--PrintTypeIds: распечатать все TypeIds.
--PrintGroup = [группа]: распечатать все идентификаторы типа группы.
--PrintAttributes = [typeid]: распечатать все атрибуты typeid.
--PrintGlobals: распечатать список глобальных объектов.
Аргументы пользователей:
--nPackets: количество пакетов для эха
Если вы хотите указать количество пакетов для эха, вы можете сделать это, установив параметр
--nПакеты аргумент в командной строке,
$ ./waf --run "царапина / myfirst --nPackets = 2"
Теперь вы должны увидеть
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.404 с)
0s UdpEchoServerApplication: UdpEchoServer ()
1с UdpEchoServerApplication: StartApplication ()
Отправлено 1024 байта на 10.1.1.2
2.25732s Получено 1024 байта от 10.1.1.1
2.25732 с. Эхо-пакет
Получено 1024 байта с 10.1.1.2
Отправлено 1024 байта на 10.1.1.2
3.25732s Получено 1024 байта от 10.1.1.1
3.25732 с. Эхо-пакет
Получено 1024 байта с 10.1.1.2
10 с. UdpEchoServerApplication: StopApplication ()
UdpEchoServerApplication: DoDispose ()
UdpEchoServerApplication: ~ UdpEchoServer ()
Вы повторили два пакета. Довольно просто, не правда ли?
Вы можете видеть, что если вы нс-3 пользователя, вы можете использовать систему аргументов командной строки для
контролировать глобальные значения и Атрибуты. Если вы автор модели, вы можете добавить новый
Атрибуты . Объекты и они будут автоматически доступны для настройки вашим
пользователей через систему командной строки. Если вы автор сценария, вы можете добавить новый
переменные в ваши скрипты и безболезненно подключите их к системе командной строки.
. трассировка Система
Весь смысл моделирования состоит в том, чтобы генерировать выходные данные для дальнейшего изучения, а нс-3
Система отслеживания является основным механизмом для этого. С нс-3 это программа на C ++, стандартная
могут использоваться средства для генерации вывода из программ C ++:
#включать
...
int main ()
{
...
std :: cout << "Значение x равно" << x << std :: endl;
...
}
Вы даже можете использовать модуль регистрации, чтобы добавить небольшую структуру к вашему решению. Там
много известных проблем, порождаемых такими подходами, и поэтому мы предоставили
общая подсистема отслеживания событий для решения проблем, которые мы считали важными.
Основные цели нс-3 Система отслеживания:
· Для основных задач система трассировки должна позволять пользователю создавать стандартные трассировки.
для популярных источников трассировки и для настройки объектов, генерирующих трассировку;
· Промежуточные пользователи должны иметь возможность расширять систему трассировки для изменения выходного формата.
сгенерированы, или для вставки новых источников трассировки, не изменяя ядро
симулятор;
· Опытные пользователи могут модифицировать ядро симулятора, добавляя новые источники и приемники трассировки.
Команда нс-3 система слежения построена на концепциях независимых источников слежения и
отслеживание раковин и единый механизм подключения источников к раковинам. Источники следов:
объекты, которые могут сигнализировать о событиях, происходящих в симуляции, и предоставлять доступ к
интересные исходные данные. Например, источник трассировки может указывать, когда пакет
полученные сетевым устройством и предоставить доступ к содержимому пакета для интересующей трассировки
раковины.
Источники трассировки бесполезны сами по себе, они должны быть «подключены» к другим частям
код, который действительно делает что-то полезное с информацией, предоставленной стоком. След
приемники являются потребителями событий и данных, предоставленных источниками трассировки. Например,
можно было бы создать приемник трассировки, который (при подключении к источнику трассировки
предыдущий пример) распечатать интересные части полученного пакета.
Обоснование этого явного разделения состоит в том, чтобы позволить пользователям прикреплять новые типы раковин к
существующие источники трассировки, не требуя редактирования и перекомпиляции ядра
симулятор. Таким образом, в приведенном выше примере пользователь мог определить новый приемник трассировки в своем
скрипт и прикрепите его к существующему источнику трассировки, определенному в ядре симуляции с помощью
редактирование только пользовательского скрипта.
В этом руководстве мы рассмотрим некоторые предопределенные источники и приемники и покажем, как
они могут быть настроены без особых усилий со стороны пользователя. См. Руководство по NS-3 или разделы с практическими рекомендациями.
для получения информации о расширенной конфигурации трассировки, включая расширение трассировки
пространство имен и создание новых источников трассировки.
ASCII трассировка
нс-3 предоставляет вспомогательные функции, которые обертывают низкоуровневую систему трассировки, чтобы помочь вам
с подробностями, связанными с настройкой некоторых легко понимаемых трассировок пакетов. если ты
Включите эту функцию, вы увидите вывод в файлах ASCII - отсюда и название. За
те, кто знаком с нс-2 на выходе этот тип трассировки аналогичен out.tr генерируется
по многим скриптам.
Давайте сразу перейдем к делу и добавим вывод трассировки ASCII в наш царапина / myfirst.cc
сценарий. Прямо перед звонком в Симулятор :: Беги ()добавьте следующие строки кода:
AsciiTraceHelper ascii;
pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));
Как и во многих других нс-3 идиомы, этот код использует вспомогательный объект, чтобы помочь создать ASCII
следы. Вторая строка содержит два вызова вложенных методов. "Внутренний" метод,
CreateFileStream () использует идиому безымянного объекта для создания объекта файлового потока на
стек (без имени объекта) и передать его вызываемому методу. Мы займемся этим
больше в будущем, но все, что вам нужно знать на данный момент, это то, что вы создаете
объект, представляющий файл с именем "myfirst.tr" и передающий его в нс-3. Вы говорите
нс-3 для решения проблем с жизненным циклом созданного объекта, а также для решения проблем
вызвано малоизвестным (преднамеренным) ограничением объектов потока C ++, относящихся к копированию
конструкторы.
Внешний звонок, чтобы EnableAsciiAll (), сообщает помощнику, что вы хотите включить ASCII
отслеживание на всех двухточечных устройствах в вашей симуляции; и вы хотите (при условии)
приемники трассировки для записи информации о перемещении пакетов в формате ASCII.
Для тех, кто знаком с нс-2, отслеживаемые события эквивалентны популярным точкам трассировки
которые регистрируют события «+», «-», «d» и «r».
Теперь вы можете собрать сценарий и запустить его из командной строки:
$ ./waf - запустить царапину / myfirst
Как вы уже много раз видели раньше, вы увидите несколько сообщений от Waf, а затем
"'build' завершена успешно" с некоторым количеством сообщений от запущенной программы.
При запуске программа создаст файл с именем мой первый.tr. Из-за пути
что Waf работает, файл не создается в локальном каталоге, он создается в
каталог верхнего уровня репозитория по умолчанию. Если вы хотите контролировать, где следы
сохранены, вы можете использовать --cwd вариант Waf, чтобы указать это. Мы этого не сделали, поэтому
нам нужно перейти в каталог верхнего уровня нашего репо и взглянуть на ASCII
файл трассировки мой первый.tr в вашем любимом редакторе.
анализ ASCII Следы
Там очень много информации в довольно плотной форме, но первое, что нужно заметить
в том, что в этом файле есть несколько отдельных строк. Может быть трудно увидеть
это ясно, если вы не расширите окно значительно.
Каждая строка в файле соответствует прослеживать мероприятие. В этом случае мы отслеживаем события на
передавать очередь присутствует в каждом сетевом устройстве точка-точка в моделировании. В
очередь передачи - это очередь, через которую каждый пакет, предназначенный для канала точка-точка
должен пройти. Обратите внимание, что каждая строка в файле трассировки начинается с одиночного символа (имеет
пробел после него). Этот символ будет иметь следующее значение:
· +: В очереди устройства произошла операция постановки в очередь;
· -: В очереди устройства произошла операция удаления из очереди;
· d: Пакет был отброшен, обычно из-за переполнения очереди;
· r: Сетевое устройство получило пакет.
Давайте подробнее рассмотрим первую строку в файле трассировки. Я сломаю это
на разделы (с отступом для ясности) со ссылочным номером слева:
+
2
/ NodeList / 0 / DeviceList / 0 / $ ns3 :: PointToPointNetDevice / TxQueue / Enqueue
ns3 :: PppHeader (
Протокол точка-точка: IP (0x0021))
ns3 :: Ipv4Header (
tos 0x0 ttl 64 id 0 протокол 17 смещение 0 флаги [нет]
длина: 1052 10.1.1.1> 10.1.1.2)
ns3 :: UdpHeader (
длина: 1032 49153> 9)
Полезная нагрузка (размер = 1024)
Первый раздел этого расширенного события трассировки (ссылочный номер 0) - это операция. Мы
есть + символ, так что это соответствует Ставить операция в очереди передачи.
Второй раздел (ссылка 1) - это время моделирования, выраженное в секундах. Ты можешь
напомним, что мы спросили Приложение UdpEchoClient чтобы начать отправку пакетов через две секунды.
Здесь мы видим подтверждение того, что это действительно происходит.
В следующем разделе примера трассировки (ссылка 2) сообщается, какой источник трассировки был создан.
это событие (выраженное в пространстве имен трассировки). Вы можете думать о пространстве имен трассировки
что-то вроде пространства имен файловой системы. Корнем пространства имен является
Список узлов. Это соответствует контейнеру, управляемому в нс-3 основной код, содержащий все
узлов, которые создаются в сценарии. Так же, как файловая система может иметь каталоги
под корнем у нас могут быть номера узлов в Список узлов. Строка / NodeList / 0
поэтому относится к нулевому узлу в Список узлов который мы обычно думаем как "узел
0 ". В каждом узле есть список установленных устройств. Этот список отображается
следующий в пространстве имен. Вы можете видеть, что это событие трассировки исходит от Список устройств / 0 который
нулевое устройство, установленное в узле.
Следующая строка, $ ns3 :: PointToPointNetDevice сообщает вам, что за устройство находится в
нулевая позиция в списке устройств для нулевого узла. Напомним, что операция + найдено по адресу
ссылка 00 означает, что в очереди передачи устройства произошла операция постановки в очередь.
Это отражается в последних сегментах «траектории трассировки», которые TxQueue / Enqueue.
Остальные разделы трассировки должны быть довольно интуитивно понятными. Ссылки 3-4 указывают
что пакет инкапсулирован в протоколе точка-точка. Ссылки 5-7 показывают, что
пакет имеет заголовок IP версии четыре и исходит от IP-адреса 10.1.1.1 и
предназначен для 10.1.1.2. Ссылки 8-9 показывают, что этот пакет имеет заголовок UDP и,
наконец, ссылка 10 показывает, что полезная нагрузка составляет ожидаемые 1024 байта.
Следующая строка в файле трассировки показывает, что тот же пакет исключен из очереди передачи.
очередь на том же узле.
Третья строка в файле трассировки показывает пакет, полученный сетевым устройством на
узел с эхо-сервером. Я воспроизвел это событие ниже.
r
2.25732
/ NodeList / 1 / DeviceList / 0 / $ ns3 :: PointToPointNetDevice / MacRx
ns3 :: Ipv4Header (
tos 0x0 ttl 64 id 0 протокол 17 смещение 0 флаги [нет]
длина: 1052 10.1.1.1> 10.1.1.2)
ns3 :: UdpHeader (
длина: 1032 49153> 9)
Полезная нагрузка (размер = 1024)
Обратите внимание, что теперь выполняется операция трассировки. r а время моделирования увеличилось до 2.25732
секунд. Если вы внимательно следовали инструкциям руководства, это означает, что у вас есть
покинул Скорость передачи данных сетевых устройств и канала задержка установить их значения по умолчанию.
Это время должно быть знакомо, как вы видели его ранее в предыдущем разделе.
Запись пространства имен источника трассировки (ссылка 02) была изменена, чтобы отразить, что это событие
поступает из узла 1 (/ NodeList / 1) и источник трассировки приема пакетов (/ MacRx). Это
вам должно быть довольно легко следить за продвижением пакета по топологии с помощью
глядя на остальные следы в файле.
ПКАП трассировка
Команда нс-3 помощники устройств также могут использоваться для создания файлов трассировки в .pcap формат.
аббревиатура pcap (обычно пишется строчными буквами) означает захват пакетов, и на самом деле это
API, который включает определение .pcap формат файла. Самая популярная программа, которая
может читать и отображать этот формат в Wireshark (ранее назывался Ethereal). Однако там
Есть много анализаторов трассировки трафика, которые используют этот формат пакета. Мы рекомендуем пользователям
использовать множество доступных инструментов для анализа трассировки pcap. В этом уроке мы
сконцентрируйтесь на просмотре трассировок pcap с помощью tcpdump.
Код, используемый для включения трассировки pcap, является однострочным.
pointToPoint.EnablePcapAll ("myfirst");
Вставьте эту строку кода после кода трассировки ASCII, который мы только что добавили в
царапина / myfirst.cc. Обратите внимание, что мы передали только строку «myfirst», а не
"myfirst.pcap" или что-то подобное. Это потому, что параметр является префиксом, а не
полное имя файла. Помощник фактически создаст файл трассировки для каждого соединения точка-точка.
устройство в моделировании. Имена файлов будут построены с использованием префикса, номера узла,
номер устройства и суффикс «.pcap».
В нашем примере сценария мы в конечном итоге увидим файлы с именем myfirst-0-0.pcap и
"myfirst-1-0.pcap", которые являются трассировками pcap для узла 0-устройства 0 и узла 1-устройства 0,
соответственно.
После того, как вы добавили строку кода для включения трассировки pcap, вы можете запустить сценарий в
обычный способ:
$ ./waf - запустить царапину / myfirst
Если вы посмотрите на каталог верхнего уровня вашего дистрибутива, вы должны увидеть три журнала
файлов: мой первый.tr это файл трассировки ASCII, который мы уже исследовали. мой первый-0-0.pcap
и мой первый-1-0.pcap - это новые файлы pcap, которые мы только что сгенерировали.
Reading выходной ТСРйитр
На этом этапе проще всего использовать ТСРйитр смотреть на ПКАП файлы.
$ tcpdump -nn -tt -r мой первый-0-0.pcap
чтение из файла myfirst-0-0.pcap, ссылочный PPP (PPP)
2.000000 IP 10.1.1.1.49153> 10.1.1.2.9: UDP, длина 1024
2.514648 IP 10.1.1.2.9> 10.1.1.1.49153: UDP, длина 1024
tcpdump -nn -tt -r мой первый-1-0.pcap
чтение из файла myfirst-1-0.pcap, ссылочный PPP (PPP)
2.257324 IP 10.1.1.1.49153> 10.1.1.2.9: UDP, длина 1024
2.257324 IP 10.1.1.2.9> 10.1.1.1.49153: UDP, длина 1024
Вы можете увидеть на свалке мой первый-0-0.pcap (клиентское устройство), что эхо-пакет
отправляется через 2 секунды в симуляцию. Если посмотреть второй дамп (мой первый-1-0.pcap)
вы можете увидеть, что этот пакет был получен через 2.257324 секунды. Вы видите, что пакет
эхом отозвалось на 2.257324 секунды во втором дампе, и, наконец, вы видите, что пакет
получил обратно у клиента в первом дампе на 2.514648 секундах.
Reading выходной Wireshark
Если вы не знакомы с Wireshark, существует веб-сайт, с которого вы можете
скачать программы и документацию: http://www.wireshark.org/.
Wireshark - это графический пользовательский интерфейс, который можно использовать для отображения этих трассировок.
файлы. Если у вас есть Wireshark, вы можете открыть каждый из файлов трассировки и отобразить
содержимое, как если бы вы захватили пакеты с помощью пакет сниффер.
СТРОИТЕЛЬСТВО ТОПОЛОГИИ
Здание a Автобусы Cеть Топология
В этом разделе мы собираемся расширить наше владение нс-3 сетевые устройства и каналы для
рассмотрим пример автобусной сети. нс-3 предоставляет сетевое устройство и канал, который мы называем CSMA
(Множественный доступ с контролем несущей).
Команда нс-3 Устройство CSMA моделирует простую сеть в духе Ethernet. Настоящий Ethernet
использует схему CSMA / CD (множественный доступ с контролем несущей и обнаружением коллизий) с
экспоненциально увеличивающаяся отсрочка для борьбы за совместно используемую среду передачи. В нс-3
Устройство и канал CSMA моделируют только часть этого.
Так же, как мы видели вспомогательные объекты топологии точка-точка при построении
топологии точка-точка, в этом разделе мы увидим эквивалентные помощники по топологии CSMA.
Внешний вид и работа этих помощников должны быть вам знакомы.
Мы предоставляем пример сценария в нашем каталоге examples / tutorial}. Этот сценарий основан на
первый.cc скрипт и добавляет сеть CSMA к моделированию точка-точка, которую мы уже
обдуманный. Давай и открой примеры / учебник / second.cc в вашем любимом редакторе. Ты
уже насмотрелся нс-3 код, чтобы понять большую часть того, что происходит в этом
пример, но мы рассмотрим весь сценарий и рассмотрим некоторые из результатов.
Так же, как в первый.cc example (и во всех примерах ns-3) файл начинается с emacs
строка режима и некоторый шаблон GPL.
Фактический код начинается с загрузки файлов включения модуля, как это было сделано в первый.cc
пример.
#include "ns3 / core-module.h"
#include "ns3 / network-module.h"
#include "ns3 / csma-module.h"
#include "ns3 / internet-module.h"
#include "ns3 / point-to-point-module.h"
#include "ns3 / applications-module.h"
#include "ns3 / ipv4-global-routing-helper.h"
Одна вещь, которая может быть на удивление полезной, - это небольшой фрагмент ASCII-арта, на котором изображен мультфильм.
топологии сети, построенной в примере. Вы найдете похожий «рисунок» в
большинство наших примеров.
В этом случае вы видите, что мы собираемся расширить наш пример точка-точка (ссылка
между узлами n0 и n1 ниже), подвесив шинную сеть с правой стороны. Уведомление
что это топология сети по умолчанию, поскольку вы можете изменять количество узлов
создан в локальной сети. Если вы установите nCsma равным единице, всего будет два узла на
LAN (канал CSMA) --- один обязательный узел и один «лишний» узел. По умолчанию есть три
«дополнительные» узлы, как показано ниже:
// Топология сети по умолчанию
//
// 10.1.1.0
// n0 -------------- n1 n2 n3 n4
// точка-точка | | | |
// ================
// ЛВС 10.1.2.0
Тогда пространство имен ns-3 будет использовал и определен компонент регистрации. Это все так же
это было в первый.cc, так что пока ничего нового.
используя пространство имен ns3;
NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
Основная программа начинается с немного другого поворота. Мы используем подробный флаг, чтобы
определить, действительно ли Приложение UdpEchoClient и Приложение UdpEchoServer каротаж
компоненты включены. По умолчанию для этого флага установлено значение true (компоненты ведения журнала включены).
но позволяет нам отключить ведение журнала во время регрессионного тестирования этого примера.
Вы увидите знакомый код, который позволит вам изменить количество устройств на
Сеть CSMA через аргумент командной строки. Мы сделали нечто подобное, когда разрешили
количество отправленных пакетов будет изменено в разделе аргументов командной строки. Последний
line гарантирует, что у вас есть хотя бы один «лишний» узел.
Код состоит из вариантов ранее охваченного API, поэтому вы должны полностью
удобно использовать следующий код на этом этапе учебника.
логический подробный = истина;
uint32_t nCsma = 3;
Командная строка командной строки;
cmd.AddValue ("nCsma", "Количество \" дополнительных \ "узлов / устройств CSMA", nCsma);
cmd.AddValue ("verbose", "Сообщать приложениям echo регистрацию, если true", verbose);
cmd.Parse(argc, argv);
если (многословно)
{
LogComponentEnable («UdpEchoClientApplication», LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
nCsma = nCsma == 0? 1: nCsma;
Следующим шагом является создание двух узлов, которые мы будем подключать через двухточечную ссылку.
Команда Нодконтейнер используется для этого так же, как это было сделано в первый.cc.
NodeContainer p2pNodes;
p2pNodes.Создать (2);
Далее мы объявляем еще один Нодконтейнер удерживать узлы, которые будут частью шины
(CSMA) сеть. Во-первых, мы просто создаем экземпляр самого объекта-контейнера.
NodeContainer csmaNodes;
csmaNodes.Add(p2pNodes.Get(1));
csmaNodes.Create(nCsma);
Следующая строка кода Получает первый узел (как если бы индекс один) из
контейнер узла точка-точка и добавляет его в контейнер узлов, которые получат CSMA
устройств. Рассматриваемый узел будет иметь устройство точка-точка. и CSMA
устройство. Затем мы создаем ряд «дополнительных» узлов, которые составляют оставшуюся часть CSMA.
сеть. Поскольку у нас уже есть один узел в сети CSMA - тот, который будет иметь
как двухточечное, так и сетевое устройство CSMA, количество «лишних» узлов означает количество
желаемых узлов в разделе CSMA минус один.
Следующий фрагмент кода уже должен быть вам хорошо знаком. Мы создаем экземпляр PointToPointHelper
и установите связанный по умолчанию Атрибуты так что мы создаем пять мегабит в секунду
передатчик на устройствах, созданных с помощью помощника и двухмиллисекундной задержки на каналах
созданный помощником.
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5 Мбит / с"));
pointToPoint.SetChannelAttribute («Задержка», StringValue («2 мс»));
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install(p2pNodes);
Затем мы создаем экземпляр NetDeviceContainer отслеживать сетевые устройства точка-точка
и мы Установите устройства на двухточечных узлах.
Мы упоминали выше, что вы увидите помощника для устройств и каналов CSMA, а также
следующие строки представляют их. В CsmaHelper работает так же, как PointToPointHelper, Но
он создает и соединяет устройства и каналы CSMA. В случае устройства CSMA и
пары каналов, обратите внимание, что скорость передачи данных определяется канал Атрибут вместо
устройство Атрибут. Это потому, что реальная сеть CSMA не позволяет смешивать, для
Например, устройства 10Base-T и 100Base-T на данном канале. Сначала мы устанавливаем скорость передачи данных на
100 мегабит в секунду, а затем установите задержку скорости света канала на 6560
наносекунды (произвольно выбранные как 1 наносекунда на фут на 100-метровом участке).
Обратите внимание, что вы можете установить Атрибут используя собственный тип данных.
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100 Мбит / с"));
csma.SetChannelAttribute («Задержка», TimeValue (NanoSeconds (6560)));
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install(csmaNodes);
Так же, как мы создали NetDeviceContainer для хранения устройств, созданных
PointToPointHelper мы создаем NetDeviceContainer для хранения устройств, созданных нашими
CsmaHelper. Мы называем Установите метод CsmaHelper установить устройства в
узлы csmaNodes Нодконтейнер.
Теперь у нас есть наши узлы, устройства и каналы, но у нас нет стеков протоколов.
настоящее время. Так же, как в первый.cc скрипт, мы будем использовать Интернет-технологии установить
эти стеки.
стек InternetStackHelper;
stack.Install(p2pNodes.Get(0));
stack.Install(csmaNodes);
Напомним, что мы взяли один из узлов из p2pузлы контейнер и добавил его в
csmaNodes контейнер. Таким образом, нам нужно установить стеки только на оставшиеся p2pузлы
узел, и все узлы в csmaNodes контейнер, чтобы покрыть все узлы в
моделирование.
Так же, как в первый.cc пример сценария, мы собираемся использовать Ipv4AddressHelper в
назначать IP-адреса интерфейсам наших устройств. Сначала мы используем сеть 10.1.1.0 для создания
два адреса, необходимые для наших двух двухточечных устройств.
IPv4AddressHelper адрес;
address.SetBase ("10.1.1.0", "255.255.255.0");
IPv4InterfaceContainer p2pInterfaces;
p2pInterfaces = адрес.Назначить (p2pDevices);
Напомним, что мы сохраняем созданные интерфейсы в контейнере, чтобы их было легко вытащить.
адресная информация позже для использования при настройке приложений.
Теперь нам нужно назначить IP-адреса интерфейсам наших устройств CSMA. Операция работает
так же, как и в случае с двухточечной связью, за исключением того, что сейчас мы выполняем операцию над
контейнер с переменным количеством устройств CSMA --- помните, что мы сделали количество
Устройства CSMA могут быть изменены с помощью аргумента командной строки. Устройства CSMA будут связаны
с IP-адресами из сети с номером 10.1.2.0 в этом случае, как показано ниже.
address.SetBase ("10.1.2.0", "255.255.255.0");
IPv4InterfaceContainer csmaInterfaces;
csmaInterfaces = адрес.Assign (csmaDevices);
Теперь у нас построена топология, но нам нужны приложения. Этот раздел будет
принципиально похож на раздел приложений первый.cc но мы собираемся
создать экземпляр сервера на одном из узлов, на котором есть устройство CSMA, а клиент - на
узел, имеющий только двухточечное устройство.
Сначала мы настраиваем эхо-сервер. Мы создаем УдпЭхосерверхелпер и предоставить необходимые
Атрибут значение конструктора, которое является номером порта сервера. Напомним, что этот порт
можно изменить позже, используя SetAttribute при желании, но мы требуем, чтобы он был
предоставляется конструктору.
UdpEchoServerHelper эхосервер (9);
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
serverApps.Start (секунды (1.0));
serverApps.Stop (секунды (10.0));
Напомним, что csmaNodes Нодконтейнер содержит один из узлов, созданных для
двухточечная сеть и нКсма «лишние» узлы. Мы хотим получить последнее из
«лишние» узлы. Нулевой вход csmaNodes контейнер будет точка-точка
узел. Тогда проще всего подумать об этом: если мы создадим один "лишний" узел CSMA, он
будет в индексе один из csmaNodes контейнер. По индукции, если мы создадим нКсма "дополнительный"
узлы последний будет по индексу нКсма. Вы видите, что это выставлено в Получите первого
строка кода.
Клиентское приложение настраивается точно так же, как мы это делали в первый.cc пример сценария. Снова,
мы обеспечиваем необходимые Атрибуты до УдпЭхоКлиентХелпер в конструкторе (в данном случае
удаленный адрес и порт). Мы говорим клиенту отправлять пакеты на сервер, мы просто
установлен на последнем из «лишних» узлов CSMA. Устанавливаем клиент на крайний левый
двухточечный узел, показанный на иллюстрации топологии.
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute («Интервал», TimeValue (секунды (1.0)));
echoClient.SetAttribute ("Размер пакета", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install(p2pNodes.Get(0));
clientApps.Start (секунды (2.0));
clientApps.Stop (секунды (10.0));
Поскольку мы фактически построили здесь межсетевое соединение, нам нужна некоторая форма межсетевого взаимодействия.
маршрутизации. нс-3 предоставляет то, что мы называем глобальной маршрутизацией, чтобы помочь вам. Глобальная маршрутизация занимает
Преимущество того факта, что вся объединенная сеть доступна в моделировании и
проходит через все узлы, созданные для моделирования, - выполняет тяжелую работу
настройка маршрутизации без необходимости настраивать роутеры.
По сути, происходит то, что каждый узел ведет себя так, как если бы это был маршрутизатор OSPF, который
мгновенно и волшебным образом связывается со всеми другими маршрутизаторами за кулисами. Каждый узел
генерирует рекламные объявления о ссылках и передает их напрямую глобальному диспетчеру маршрутов
который использует эту глобальную информацию для построения таблиц маршрутизации для каждого узла. Параметр
Эта форма маршрутизации является однострочным:
Ipv4GlobalRoutingHelper :: PopulateRoutingTables ();
Затем мы включаем трассировку pcap. Первая строка кода для включения трассировки pcap в
двухточечный помощник должен быть вам уже знаком. Вторая строка включает pcap
трассировка в помощнике CSMA, и есть дополнительный параметр, с которым вы еще не сталкивались.
pointToPoint.EnablePcapAll («второй»);
csma.EnablePcap ("второй", csmaDevices.Get (1), истина);
Сеть CSMA представляет собой многоточечную сеть. Это означает, что могут (и находятся в
в этом случае) несколько конечных точек на общем носителе. Каждая из этих конечных точек имеет сеть
связанное с ним устройство. Есть две основные альтернативы сбору следов.
информация из такой сети. Один из способов - создать файл трассировки для каждого сетевого устройства.
и хранить только те пакеты, которые излучаются или потребляются этим сетевым устройством. По-другому
состоит в том, чтобы выбрать одно из устройств и перевести его в режим неразборчивой связи. Это единственное устройство тогда
«обнюхивает» сеть на наличие всех пакетов и сохраняет их в одном файле pcap. Вот как
ТСРйитр, например, работает. Этот последний параметр сообщает помощнику CSMA, следует ли
организовать перехват пакетов в беспорядочном режиме.
В этом примере мы собираемся выбрать одно из устройств в сети CSMA и спросить его
для беспорядочного обнюхивания сети, тем самым имитируя то, что ТСРйитр сделал бы.
Если бы вы были на машине с Linux, вы могли бы сделать что-нибудь вроде ТСРйитр -i eth0 , чтобы получить
след. В этом случае мы указываем устройство с помощью csmaDevices.Get(1), который выбирает
первое устройство в контейнере. Установка последнего параметра в значение true разрешает беспорядочные связи
ловит.
Последний раздел кода просто запускает и очищает симуляцию точно так же, как первый.cc
пример.
Симулятор :: Беги ();
Симулятор :: Уничтожить ();
0 вернуться;
}
Чтобы запустить этот пример, скопируйте второй.cc пример скрипта в рабочий каталог
и используйте waf для сборки так же, как вы это делали с первый.cc пример. Если вы в
каталог верхнего уровня репозитория, который вы только что набрали,
$ cp examples / tutorial / second.cc scratch / mysecond.cc
$ ./ваф
Предупреждение: мы используем файл второй.cc в качестве одного из наших регрессионных тестов, чтобы убедиться, что он работает
именно так, как мы думаем, чтобы сделать ваше обучение положительным.
Это означает, что исполняемый файл с именем второй уже существует в проекте. Чтобы избежать каких-либо
путаница в том, что вы выполняете, переименуйте в мойсекундный.cc предполагают
выше.
Если вы неукоснительно следуете руководству (да, не так ли), у вас все равно будет
набор переменных NS_LOG, поэтому очистите эту переменную и запустите программу.
$ экспорт NS_LOG =
$ ./waf - запустить царапину / мою секунду
Поскольку мы настроили эхо-приложения UDP для ведения журнала так же, как в первый.cc, Вы будете
увидеть аналогичный результат при запуске сценария.
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.415 с)
Отправлено 1024 байта на 10.1.2.4
Получено 1024 байта с 10.1.1.1
Получено 1024 байта с 10.1.2.4
Напомним, что первое сообщение "Отправлено 1024 байт в 10.1.2.4, "- эхо-клиент UDP
отправка пакета на сервер. В этом случае сервер находится в другой сети.
(10.1.2.0). Второе сообщение "Полученный 1024 байт от 10.1.1.1, "из эха UDP
сервер, генерируемый при получении эхо-пакета. Последнее сообщение "Полученный 1024
байт от 10.1.2.4, "поступает от эхо-клиента, что указывает на то, что он получил свой эхо-сигнал.
обратно с сервера.
Если вы теперь пойдете и посмотрите в каталог верхнего уровня, вы найдете три файла трассировки:
second-0-0.pcap second-1-0.pcap second-2-0.pcap
Давайте посмотрим на названия этих файлов. Все они имеют одинаковую форму,
- - .pcap. Например, первый файл в списке - это
второй-0-0.pcap который представляет собой трассировку pcap от нулевого узла, нулевого устройства. Это
двухточечное сетевое устройство на нулевом узле. Файл второй-1-0.pcap это трассировка pcap для
нулевое устройство на первом узле, а также сетевое устройство точка-точка; и файл второй-2-0.pcap is
трассировка pcap для нулевого устройства на втором узле.
Если вы вернетесь к иллюстрации топологии в начале раздела, вы увидите
этот нулевой узел - это крайний левый узел двухточечного соединения, а первый узел - это узел
который имеет как двухточечное устройство, так и устройство CSMA. Вы увидите, что второй узел
первый «лишний» узел в сети CSMA и его нулевое устройство были выбраны в качестве устройства
для захвата трассировки в беспорядочном режиме.
Теперь давайте проследим за эхо-пакетом через объединенную сеть. Сначала выполните tcpdump файла
файл трассировки для самого левого двухточечного узла --- нулевого узла.
$ tcpdump -nn -tt -r второй-0-0.pcap
Вы должны увидеть содержимое файла pcap:
чтение из файла second-0-0.pcap, канальный PPP (PPP)
2.000000 IP 10.1.1.1.49153> 10.1.2.4.9: UDP, длина 1024
2.017607 IP 10.1.2.4.9> 10.1.1.1.49153: UDP, длина 1024
Первая строка дампа указывает, что тип связи - PPP (точка-точка), который мы
ожидать. Затем вы видите, что эхо-пакет покидает нулевой узел через устройство, связанное с IP.
адрес 10.1.1.1 ведет к IP-адресу 10.1.2.4 (крайний правый узел CSMA). Этот пакет
будет перемещаться по каналу точка-точка и приниматься сетевым устройством точка-точка на
узел один. Давайте взглянем:
$ tcpdump -nn -tt -r второй-1-0.pcap
Теперь вы должны увидеть выходные данные трассировки pcap на другой стороне двухточечной связи:
чтение из файла second-1-0.pcap, канальный PPP (PPP)
2.003686 IP 10.1.1.1.49153> 10.1.2.4.9: UDP, длина 1024
2.013921 IP 10.1.2.4.9> 10.1.1.1.49153: UDP, длина 1024
Здесь мы видим, что тип ссылки также является PPP, как и следовало ожидать. Вы видите пакет с IP
адрес 10.1.1.1 (который был отправлен через 2.000000 10.1.2.4 XNUMX секунд) направился к IP-адресу XNUMX
появляются в этом интерфейсе. Теперь внутри этого узла пакет будет перенаправлен на
интерфейс CSMA, и мы должны увидеть, как он выскакивает на этом устройстве, направляясь к своему окончательному
место назначения.
Помните, что мы выбрали узел 2 в качестве узла беспорядочного перехватчика для сети CSMA, поэтому
давайте тогда посмотрим на second-2-0.pcap и посмотрим, там ли он.
$ tcpdump -nn -tt -r второй-2-0.pcap
Теперь вы должны увидеть беспорядочный дамп узла два, нулевое устройство:
чтение из файла second-2-0.pcap, линк-тип EN10MB (Ethernet)
2.007698 ARP, запрос у кого-есть 10.1.2.4 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.1, длина 50
2.007710 ARP, ответ 10.1.2.4 - в 00: 00: 00: 00: 00: 06, длина 50
2.007803 IP 10.1.1.1.49153> 10.1.2.4.9: UDP, длина 1024
2.013815 ARP, запрос у кого-есть 10.1.2.1 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.4, длина 50
2.013828 ARP, ответ 10.1.2.1 - в 00: 00: 00: 00: 00: 03, длина 50
2.013921 IP 10.1.2.4.9> 10.1.1.1.49153: UDP, длина 1024
Как видите, тип канала связи теперь "Ethernet". Но кое-что новое появилось. В
потребности автобусной сети ARP, протокол разрешения адресов. Узел знает, что нужно отправить
пакет на IP-адрес 10.1.2.4, но он не знает MAC-адрес
соответствующий узел. Он вещает в сети CSMA (ff: ff: ff: ff: ff: ff), запрашивая
устройство с IP-адресом 10.1.2.4. В этом случае самый правый узел отвечает, говоря, что
находится по MAC-адресу 00: 00: 00: 00: 00: 06. Обратите внимание, что второй узел не участвует в этом напрямую.
exchange, но отслеживает сеть и сообщает обо всем увиденном трафике.
Этот обмен можно увидеть в следующих строках:
2.007698 ARP, запрос у кого-есть 10.1.2.4 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.1, длина 50
2.007710 ARP, ответ 10.1.2.4 - в 00: 00: 00: 00: 00: 06, длина 50
Затем узел XNUMX, устройство XNUMX идет вперед и отправляет эхо-пакет на эхо-сервер UDP в
IP-адрес 10.1.2.4.
2.007803 IP 10.1.1.1.49153> 10.1.2.4.9: UDP, длина 1024
Сервер получает эхо-запрос и переворачивает пакет, пытаясь отправить его обратно в
источник. Сервер знает, что этот адрес находится в другой сети, к которой он обращается через
IP-адрес 10.1.2.1. Это потому, что мы инициализировали глобальную маршрутизацию, и она рассчитала все
из этого для нас. Но узел эхо-сервера не знает MAC-адрес первого
Узел CSMA, поэтому он должен для него ARP, как и первый узел CSMA.
2.013815 ARP, запрос у кого-есть 10.1.2.1 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.4, длина 50
2.013828 ARP, ответ 10.1.2.1 - в 00: 00: 00: 00: 00: 03, длина 50
Затем сервер отправляет эхо обратно на узел пересылки.
2.013921 IP 10.1.2.4.9> 10.1.1.1.49153: UDP, длина 1024
Оглядываясь назад на крайний правый узел двухточечной связи,
$ tcpdump -nn -tt -r второй-1-0.pcap
Теперь вы можете видеть, что отраженный пакет возвращается по каналу точка-точка как последний
строка дампа трассировки.
чтение из файла second-1-0.pcap, канальный PPP (PPP)
2.003686 IP 10.1.1.1.49153> 10.1.2.4.9: UDP, длина 1024
2.013921 IP 10.1.2.4.9> 10.1.1.1.49153: UDP, длина 1024
Наконец, вы можете вернуться к узлу, который вызвал эхо.
$ tcpdump -nn -tt -r второй-0-0.pcap
и видим, что отраженный пакет возвращается к источнику в 2.007602 секунды,
чтение из файла second-0-0.pcap, канальный PPP (PPP)
2.000000 IP 10.1.1.1.49153> 10.1.2.4.9: UDP, длина 1024
2.017607 IP 10.1.2.4.9> 10.1.1.1.49153: UDP, длина 1024
Напомним, что мы добавили возможность контролировать количество устройств CSMA в
моделирование с помощью аргумента командной строки. Вы можете изменить этот аргумент так же, как когда
мы рассмотрели изменение количества пакетов, отраженных в первый.cc пример. Попробуй бежать
программа с количеством "лишних" устройств равным четырем:
$ ./waf --run "царапина / моя секунда --nCsma = 4"
Теперь вы должны увидеть,
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.405 с)
За время 2 с клиент отправил 1024 байта на порт 10.1.2.5 9.
В момент времени 2.0118s сервер получил 1024 байта с порта 10.1.1.1 49153.
В момент времени 2.0118s сервер отправил 1024 байта на порт 10.1.1.1 49153
В момент времени 2.02461s клиент получил 1024 байта с порта 10.1.2.5 9.
Обратите внимание, что эхо-сервер теперь перемещен на последний из узлов CSMA, который является
10.1.2.5 вместо случая по умолчанию 10.1.2.4.
Возможно, вас не устроит файл трассировки, созданный сторонним наблюдателем в
сеть CSMA. Возможно, вы действительно захотите получить трассировку с одного устройства, но не можете
интересоваться любым другим трафиком в сети. Вы можете сделать это довольно легко.
Давайте посмотрим на царапина / mysecond.cc и добавьте этот код, чтобы мы могли быть больше
конкретный. нс-3 помощники предоставляют методы, которые принимают номер узла и номер устройства как
параметры. Идите вперед и замените ВключитьPcap звонки с звонками ниже.
pointToPoint.EnablePcap («второй», p2pNodes.Get (0) -> GetId (), 0);
csma.EnablePcap («второй», csmaNodes.Get (nCsma) -> GetId (), 0, false);
csma.EnablePcap ("второй", csmaNodes.Get (nCsma-1) -> GetId (), 0, false);
Мы знаем, что хотим создать файл pcap с базовым именем second, а также знаем, что
что интересующее устройство в обоих случаях будет нулевым, поэтому эти параметры не
очень интересно.
Чтобы получить номер узла, у вас есть два варианта: во-первых, узлы нумеруются в
монотонно возрастающая мода, начиная с нуля в том порядке, в котором вы создали
их. Один из способов получить номер узла - вычислить его «вручную»,
обдумывая порядок создания узла. Если вы посмотрите на топологию сети
иллюстрацию в начале файла, мы сделали это для вас, и вы можете видеть, что
последний узел CSMA будет номером узла нКсма + 1. Такой подход может раздражать
сложно в больших моделированиях.
Альтернативный способ, который мы здесь используем, - это осознать, что НодКонтейнеры содержать
указатели на нс-3 Узел Объекты. В Узел У объекта есть метод, называемый GetId который будет
верните идентификатор этого узла, который является номером узла, который мы ищем. Пойдем взглянем на
Doxygen для Узел и найдите этот метод, который находится ниже в нс-3 основной код
чем мы видели до сих пор; но иногда приходится усердно искать полезные вещи.
Перейдите к документации Doxygen для вашего выпуска (помните, что вы можете найти ее на
сайт проекта). Вы можете добраться до Узел документацию, просмотрев
Вкладка «Классы» и прокрутите вниз «Список классов», пока не найдете ns3 :: Узел. Выбирать
ns3 :: Узел и вы перейдете к документации по Узел класс. Если ты сейчас
прокрутите вниз до GetId метод и выберите его, вы попадете в подробный
документация по методу. С помощью GetId метод может сделать определение номеров узлов
намного проще в сложных топологиях.
Давайте удалим старые файлы трассировки из каталога верхнего уровня, чтобы избежать путаницы с
что здесь происходит,
$ rm * .pcap
$ rm * .tr
Если вы создадите новый скрипт и запустите настройку моделирования нКсма к 100,
$ ./waf --run "царапина / моя секунда --nCsma = 100"
вы увидите следующий результат:
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.407 с)
За время 2 с клиент отправил 1024 байта на порт 10.1.2.101 9.
В момент времени 2.0068s сервер получил 1024 байта с порта 10.1.1.1 49153.
В момент времени 2.0068s сервер отправил 1024 байта на порт 10.1.1.1 49153
В момент времени 2.01761s клиент получил 1024 байта с порта 10.1.2.101 9.
Обратите внимание, что теперь эхо-сервер находится по адресу 10.1.2.101, что соответствует 100
"лишние" узлы CSMA с эхо-сервером на последнем. Если вы перечислите файлы pcap в
каталог верхнего уровня, который вы увидите,
second-0-0.pcap second-100-0.pcap second-101-0.pcap
Файл трассировки второй-0-0.pcap это "крайнее левое" устройство связи точка-точка, которое является эхом
источник пакета. Файл второй-101-0.pcap соответствует крайнему правому устройству CSMA, которое
здесь находится эхо-сервер. Вы могли заметить, что последний параметр на
вызов для включения трассировки pcap на узле эхо-сервера был ложным. Это означает, что след
собранный на этом узле был в неразборчивом режиме.
Чтобы проиллюстрировать разницу между беспорядочными и неполными связями, мы также
запросил неразборчивую трассировку для предпоследнего узла. Давай, взгляни на
ТСРйитр для второй-100-0.pcap.
$ tcpdump -nn -tt -r второй-100-0.pcap
Теперь вы можете видеть, что узел 100 действительно является сторонним наблюдателем при обмене эхом. Единственный
пакеты, которые он получает, являются запросами ARP, которые транслируются на весь CSMA
сеть.
чтение из файла second-100-0.pcap, линк-тип EN10MB (Ethernet)
2.006698 ARP, запрос у кого-есть 10.1.2.101 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.1, длина 50
2.013815 ARP, запрос у кого-есть 10.1.2.1 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.101, длина 50
А теперь взгляните на ТСРйитр для второй-101-0.pcap.
$ tcpdump -nn -tt -r второй-101-0.pcap
Теперь вы можете видеть, что узел 101 действительно является участником обмена эхом.
чтение из файла second-101-0.pcap, линк-тип EN10MB (Ethernet)
2.006698 ARP, запрос у кого-есть 10.1.2.101 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.1, длина 50
2.006698 ARP, ответ 10.1.2.101 - в 00: 00: 00: 00: 00: 67, длина 50
2.006803 IP 10.1.1.1.49153> 10.1.2.101.9: UDP, длина 1024
2.013803 ARP, запрос у кого-есть 10.1.2.1 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.101, длина 50
2.013828 ARP, ответ 10.1.2.1 - в 00: 00: 00: 00: 00: 03, длина 50
2.013828 IP 10.1.2.101.9> 10.1.1.1.49153: UDP, длина 1024
Модели, Атрибуты и Реальность
Это удобное место, чтобы сделать небольшую экскурсию и сделать важный момент. Это может
или может быть неочевидным для вас, но всякий раз, когда вы используете симуляцию, важно
точно понимать, что моделируется, а что нет. Заманчиво, например,
думайте об устройствах и каналах CSMA, использованных в предыдущем разделе, как о реальных
Устройства Ethernet; и ожидать, что результат моделирования напрямую отразит то, что произойдет
в реальном Ethernet. Это не тот случай.
Модель по определению - это абстракция реальности. В конечном итоге ответственность
автора сценария моделирования для определения так называемого «диапазона точности» и «области
применимости »моделирования в целом, а следовательно, и его составных частей.
В некоторых случаях, как CSMA, довольно легко определить, что смоделирован. От
чтение описания модели (csma.h) вы можете обнаружить, что нет обнаружения столкновений
в модели CSMA и решите, насколько применимо его использование в вашей симуляции или
предостережения, которые вы можете включить в свои результаты. В других случаях это может быть довольно просто
чтобы настроить поведение, которое может не соответствовать любой реальности, которую вы можете пойти и купить. Это
окажется полезным потратить некоторое время на расследование нескольких таких случаев, и как
вы легко можете выйти за пределы реальности в своих симуляциях.
Как вы видели, нс-3 приводит Атрибуты который пользователь может легко настроить для изменения модели
поведение. Рассмотрим два из Атрибуты CsmaNetDevice: МТУ и
Режим инкапсуляции, МТУ указывает Максимальный блок передачи на
устройство. Это размер самого большого блока данных протокола (PDU), который устройство может
Отправить.
По умолчанию значение MTU составляет 1500 байтов. CsmaNetDevice. Это значение по умолчанию соответствует числу
содержится в RFC 894, «Стандарт передачи дейтаграмм IP через Ethernet.
Сети ». Число фактически получено из максимального размера пакета для 10Base5.
(полнофункциональный Ethernet) сети - 1518 байт. Если вычесть инкапсуляцию DIX
накладные расходы для пакетов Ethernet (18 байт) вы получите максимально возможный размер данных
(MTU) 1500 байт. Также можно обнаружить, что МТУ для сетей IEEE 802.3 - 1492
байтов. Это связано с тем, что инкапсуляция LLC / SNAP добавляет дополнительные восемь байтов служебных данных к
пакет. В обоих случаях базовое оборудование может отправлять только 1518 байт, но данные
размер другой.
Чтобы установить режим инкапсуляции, CsmaNetDevice обеспечивает Атрибут под названием
Режим инкапсуляции который может принимать значения Dix or ООО. Они соответствуют Ethernet
и кадрирование LLC / SNAP соответственно.
Если уйти МТУ на 1500 байт и меняет режим инкапсуляции на ООО, результат
будет сетью, которая инкапсулирует 1500-байтовые PDU с кадрированием LLC / SNAP, что приведет к
пакеты по 1526 байт, что было бы недопустимо во многих сетях, поскольку они могут передавать
максимум 1518 байт на пакет. Скорее всего, это приведет к моделированию, которое
довольно тонко не отражает той реальности, которую вы могли ожидать.
Чтобы усложнить картину, существуют jumbo-кадры (1500 <MTU <= 9000 байт) и
супер-большие (MTU> 9000 байт) кадры, которые официально не санкционированы IEEE, но
доступен в некоторых высокоскоростных (гигабитных) сетях и сетевых адаптерах. Можно было оставить
установлен режим инкапсуляции Dix, и установите МТУ Атрибут на CsmaNetDevice до 64000 байт
- даже если связанный CsmaChannel Скорость передачи данных был установлен на 10 мегабит в секунду. Этот
по сути, смоделирует коммутатор Ethernet, сделанный из 1980Base10 в стиле 5-х годов.
сети, поддерживающие супер-большие датаграммы. Это определенно не то, что было
когда-либо, и вряд ли когда-либо будет изготовлен, но его довольно легко настроить.
В предыдущем примере вы использовали командную строку для создания симуляции, в которой было 100
CSMA узлы. Вы могли бы так же легко создать симуляцию с 500 узлами. если ты
на самом деле моделировали эту сеть 10Base5 вампира, максимальная длина полной спецификации
Длина кабеля Ethernet составляет 500 метров, с минимальным расстоянием между ответвлениями 2.5 метра. Это значит там
в реальной сети может быть только 200 ответвлений. Вы могли довольно легко построить нелегальный
сеть таким же образом. Это может привести, а может и не привести к значимому моделированию.
в зависимости от того, что вы пытаетесь моделировать.
Подобные ситуации могут происходить во многих местах в нс-3 и в любом симуляторе. Например,
вы можете расположить узлы таким образом, чтобы они занимали одинаковое пространство в
в то же время, или вы можете настроить усилители или уровни шума, которые нарушают
основные законы физики.
нс-3 обычно способствует гибкости, и многие модели позволяют свободно настраивать Атрибуты
без попытки навязать какую-либо произвольную согласованность или конкретную базовую спецификацию.
Главное, что нужно сделать - это то, что нс-3 обеспечит сверхгибкую базу
для вас, чтобы поэкспериментировать. Вам решать, что вы запрашиваете у системы.
сделать и убедиться, что моделирование, которое вы создаете, имеет какое-то значение, а некоторые
связь с определенной вами реальностью.
Здание a Беспроводной сети Cеть Топология
В этом разделе мы собираемся расширить наши знания о нс-3 сетевые устройства и
каналы, чтобы охватить пример беспроводной сети. нс-3 предоставляет набор моделей 802.11
которые пытаются обеспечить точную реализацию на уровне MAC спецификации 802.11
и "не очень медленная" модель физического уровня спецификации 802.11a.
Так же, как мы видели вспомогательные объекты топологии точка-точка и CSMA, когда
при построении двухточечных топологий мы увидим эквивалентные Wi-Fi помощники по топологии в
эта секция. Внешний вид и работа этих помощников должны показаться довольно знакомыми.
вас.
Мы предоставляем пример сценария в нашем примеры / учебник каталог. Этот сценарий основан на
второй.cc скрипт и добавляет сеть Wi-Fi. Давай и открой
примеры / учебник / third.cc в вашем любимом редакторе. Вы уже насмотрелись
нс-3 код, чтобы понять большую часть того, что происходит в этом примере, но есть несколько новых
вещи, поэтому мы рассмотрим весь сценарий и рассмотрим некоторые из результатов.
Так же, как в второй.cc пример (и во всех нс-3 примеры) файл начинается с emacs
строка режима и некоторый шаблон GPL.
Взгляните на рисунок ASCII (воспроизведенный ниже), который показывает топологию сети по умолчанию.
построенный в примере. Как видите, мы собираемся расширить наш пример.
повесив беспроводную сеть с левой стороны. Обратите внимание, что это сеть по умолчанию
топология, поскольку вы можете фактически варьировать количество узлов, созданных на проводной и беспроводной
сети. Так же, как в второй.cc случай сценария, если вы измените нКсма, это даст вам
количество «лишних» узлов CSMA. Точно так же вы можете установить nWi-Fi контролировать, сколько STA
Узлы (станции) создаются при моделировании. Всегда будет один AP (точка доступа)
узел в беспроводной сети. По умолчанию есть три "лишних" узла CSMA и три
беспроводной STA узлы.
Код начинается с загрузки файлов включения модуля, как это было сделано в второй.cc пример.
Есть пара новых включений, соответствующих модулю Wi-Fi и мобильности.
модуль, который мы обсудим ниже.
#include "ns3 / core-module.h"
#include "ns3 / point-to-point-module.h"
#include "ns3 / network-module.h"
#include "ns3 / applications-module.h"
#include "ns3 / wifi-module.h"
#include "ns3 / Mobility-module.h"
#include "ns3 / csma-module.h"
#include "ns3 / internet-module.h"
На иллюстрации топологии сети:
// Топология сети по умолчанию
//
// Wi-Fi 10.1.3.0
// точка доступа
// * * * *
// | | | | 10.1.1.0
// n5 n6 n7 n0 -------------- n1 n2 n3 n4
// точка-точка | | | |
// ================
// ЛВС 10.1.2.0
Вы можете видеть, что мы добавляем новое сетевое устройство к узлу в левой части окна.
соединение точка-точка, которое становится точкой доступа к беспроводной сети. Количество
беспроводные узлы STA создаются для заполнения новой сети 10.1.3.0, как показано слева
сторона иллюстрации.
После иллюстрации нс-3 пространство имен использовал и определен компонент регистрации.
К настоящему времени все это должно быть хорошо знакомо.
используя пространство имен ns3;
NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
Основная программа начинается так же, как второй.cc добавив некоторые параметры командной строки для
включение или отключение компонентов ведения журнала и изменение количества созданных устройств.
логический подробный = истина;
uint32_t nCsma = 3;
uint32_t nWi-Fi = 3;
Командная строка командной строки;
cmd.AddValue ("nCsma", "Количество \" дополнительных \ "узлов / устройств CSMA", nCsma);
cmd.AddValue («nWifi», «Количество устройств Wi-Fi STA», nWifi);
cmd.AddValue ("verbose", "Сообщать приложениям echo регистрацию, если true", verbose);
cmd.Parse (argc, argv);
если (многословно)
{
LogComponentEnable («UdpEchoClientApplication», LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
}
Как и во всех предыдущих примерах, следующим шагом будет создание двух узлов, которые мы будем
подключиться через двухточечный канал.
NodeContainer p2pNodes;
p2pNodes.Создать (2);
Далее мы видим старого друга. Мы создаем экземпляр PointToPointHelper и установите связанный
по умолчанию Атрибуты так что мы создаем передатчик со скоростью пять мегабит в секунду на устройствах
создается с помощью помощника и задержки в две миллисекунды на каналах, созданных помощником.
Затем мы Внутренний устройства на узлах и канал между ними.
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5 Мбит / с"));
pointToPoint.SetChannelAttribute («Задержка», StringValue («2 мс»));
NetDeviceContainer p2pDevices;
p2pDevices = pointToPoint.Install(p2pNodes);
Далее мы объявляем еще один Нодконтейнер удерживать узлы, которые будут частью шины
(CSMA) сеть.
NodeContainer csmaNodes;
csmaNodes.Add(p2pNodes.Get(1));
csmaNodes.Create(nCsma);
Следующая строка кода Получает первый узел (как если бы индекс один) из
контейнер узла точка-точка и добавляет его в контейнер узлов, которые получат CSMA
устройств. Рассматриваемый узел будет иметь двухточечное устройство и CSMA.
устройство. Затем мы создаем ряд «дополнительных» узлов, которые составляют оставшуюся часть CSMA.
сеть.
Затем мы создаем экземпляр CsmaHelper и установите Атрибуты как мы сделали в предыдущем примере.
Мы создаем NetDeviceContainer для отслеживания созданных сетевых устройств CSMA, а затем мы
Установите Устройства CSMA на выбранных узлах.
CsmaHelper csma;
csma.SetChannelAttribute ("DataRate", StringValue ("100 Мбит / с"));
csma.SetChannelAttribute («Задержка», TimeValue (NanoSeconds (6560)));
NetDeviceContainer csmaDevices;
csmaDevices = csma.Install(csmaNodes);
Далее мы собираемся создать узлы, которые будут частью сети Wi-Fi. Мы
собирается создать несколько узлов "станции", как указано в аргументе командной строки, и
мы собираемся использовать "крайний левый" узел двухточечной связи в качестве узла для
точка доступа.
NodeContainer wifiStaNodes;
wifiStaNodes.Create (нВифи);
NodeContainer wifiApNode = p2pNodes.Get (0);
Следующий фрагмент кода создает устройства Wi-Fi и канал связи между
эти узлы Wi-Fi. Сначала мы настраиваем PHY и помощники каналов:
YansWifiChannelHelper channel = YansWifiChannelHelper :: Default ();
YansWifiPhyHelper phy = YansWifiPhyHelper :: Default ();
Для простоты в этом коде используются конфигурация уровня PHY и модели каналов по умолчанию.
которые задокументированы в документации API doxygen для
YansWifiChannelHelper :: По умолчанию и YansWifiPhyHelper :: По умолчанию методы. Когда-то эти объекты
созданы, мы создаем объект канала и связываем его с нашим менеджером объектов уровня PHY
чтобы убедиться, что все объекты уровня PHY, созданные ЯнсWifiPhyHelper поделиться
один и тот же базовый канал, то есть они используют одну и ту же беспроводную среду и могут
общение и вмешиваться:
phy.SetChannel(channel.Create());
Как только PHY-помощник настроен, мы можем сосредоточиться на уровне MAC. Здесь мы выбираем работу
с MAC-адресами, отличными от Qos, поэтому мы используем объект NqosWifiMacHelper для установки параметров MAC.
WifiHelper wifi = WifiHelper :: Default ();
wifi.SetRemoteStationManager ("ns3 :: AarfWifiManager");
NqosWifiMacHelper mac = NqosWifiMacHelper :: Default ();
Команда SetRemoteStationManager сообщает помощнику, какой алгоритм управления скоростью
использовать. Здесь он просит помощника использовать алгоритм AARF --- детали, конечно,
доступно в Doxygen.
Затем мы настраиваем тип MAC, SSID инфраструктуры сети, которую мы хотим
настройте и убедитесь, что наши станции не проводят активное зондирование:
Ssid ssid = Ssid ("ns-3-ssid");
mac.SetType ("ns3 :: StaWifiMac",
"Ssid", SsidValue (ssid),
«ActiveProbing», BooleanValue (false));
Этот код сначала создает объект идентификатора набора услуг 802.11 (SSID), который будет использоваться.
установить значение "Ssid" Атрибут реализации уровня MAC. Особый
вид MAC-уровня, который будет создан помощником, определяется Атрибут как из
тип "ns3 :: StaWifiMac". Использование NqosWifiMacПомощник гарантирует, что
"QosSupported" Атрибут для созданных MAC-объектов установлено false. Сочетание этих
две конфигурации означают, что следующий созданный экземпляр MAC будет не-QoS не-AP
станция (STA) в инфраструктуре BSS (т. е. BSS с AP). Наконец,
«Активное зондирование» Атрибут установлено значение false. Это означает, что зондирующие запросы не будут
отправлено MAC-адресами, созданными этим помощником.
После того, как все параметры станции будут полностью настроены, как на MAC, так и на PHY
слоев, мы можем использовать наши теперь знакомые Установите способ создания устройств Wi-Fi из этих
станций:
staDevices NetDeviceContainer;
staDevices = wifi.Install (phy, mac, wifiStaNodes);
Мы настроили Wi-Fi для всех наших узлов STA, и теперь нам нужно настроить AP
(точка доступа) узел. Мы начинаем этот процесс с изменения значения по умолчанию Атрибуты
NqosWifiMacПомощник чтобы отразить требования AP.
mac.SetType ("ns3 :: ApWifiMac",
"Ssid", SsidValue (ssid));
В этом случае NqosWifiMacПомощник собирается создать MAC-уровни "ns3 :: ApWifiMac",
последний указывает, что должен быть создан экземпляр MAC, настроенный как AP, с
вспомогательный тип, подразумевающий, что "QosSupported" Атрибут должно быть установлено значение false - отключение
Поддержка QoS в стиле 802.11e / WMM на созданных точках доступа.
Следующие строки создают одну точку доступа, которая использует тот же набор PHY-уровня. Атрибуты (И
канал) как станции:
apDevices NetDeviceContainer;
apDevices = wifi.Install (phy, mac, wifiApNode);
Теперь мы собираемся добавить модели мобильности. Мы хотим, чтобы узлы STA были мобильными, блуждающими
внутри ограничительной рамки, и мы хотим сделать узел AP неподвижным. Мы используем
Мобильность чтобы облегчить нам задачу. Сначала мы создаем экземпляр Мобильность объект
и установить некоторые Атрибуты управление функциональностью «распределителя позиций».
MobilityHelper мобильность;
мобильность.SetPositionAllocator ("ns3 :: GridPositionAllocator",
«MinX», DoubleValue (0.0),
«MinY», DoubleValue (0.0),
«DeltaX», DoubleValue (5.0),
"DeltaY", DoubleValue (10.0),
"GridWidth", UintegerValue (3),
«LayoutType», StringValue («RowFirst»));
Этот код сообщает помощнику по мобильности использовать двумерную сетку для первоначального размещения
Узлы STA. Не стесняйтесь исследовать Doxygen для класса ns3 :: GridPositionAllocator видеть
именно то, что делается.
Мы расположили наши узлы на исходной сетке, но теперь нам нужно сказать им, как двигаться.
Мы выбираем RandomWalk2dMobilityModel в котором узлы перемещаются в случайном направлении на
случайная скорость внутри ограничивающей рамки.
мобильность.SetMobilityModel ("ns3 :: RandomWalk2dMobilityModel",
«Границы», RectangleValue (Rectangle (-50, 50, -50, 50)));
Теперь мы говорим Мобильность для установки моделей мобильности на узлы STA.
мобильность.Установить (wifiStaNodes);
Мы хотим, чтобы точка доступа оставалась в фиксированном положении во время симуляции. Мы
добиться этого, установив модель мобильности для этого узла как
ns3 :: ConstantPositionMobilityModel:
мобильность.SetMobilityModel ("ns3 :: ConstantPositionMobilityModel");
мобильность.Установить (wifiApNode);
Теперь у нас есть наши узлы, устройства и каналы, а также выбраны модели мобильности для
Узлы Wi-Fi, но у нас нет стеков протоколов. Так же, как мы делали ранее многие
раз мы будем использовать Интернет-технологии установить эти стеки.
стек InternetStackHelper;
stack.Install(csmaNodes);
stack.Install(wifiApNode);
stack.Install(wifiStaNodes);
Так же, как в второй.cc пример сценария, мы собираемся использовать Ipv4AddressHelper в
назначать IP-адреса интерфейсам наших устройств. Сначала мы используем сеть 10.1.1.0 для создания
два адреса, необходимые для наших двух двухточечных устройств. Затем используем сеть 10.1.2.0
для назначения адресов в сеть CSMA, а затем мы назначаем адреса из сети 10.1.3.0
как к устройствам STA, так и к AP в беспроводной сети.
IPv4AddressHelper адрес;
address.SetBase ("10.1.1.0", "255.255.255.0");
IPv4InterfaceContainer p2pInterfaces;
p2pInterfaces = адрес.Назначить (p2pDevices);
address.SetBase ("10.1.2.0", "255.255.255.0");
IPv4InterfaceContainer csmaInterfaces;
csmaInterfaces = адрес.Assign (csmaDevices);
address.SetBase ("10.1.3.0", "255.255.255.0");
адрес.Assign (staDevices);
адрес.Assign (apDevices);
Мы помещаем эхо-сервер в "крайний правый" узел на иллюстрации в начале
файл. Мы делали это раньше.
UdpEchoServerHelper эхосервер (9);
ApplicationContainer serverApps = echoServer.Install (csmaNodes.Get (nCsma));
serverApps.Start (секунды (1.0));
serverApps.Stop (секунды (10.0));
И мы помещаем эхо-клиента на последний созданный нами узел STA, указывая его на сервер на
сеть CSMA. Мы тоже видели подобные операции раньше.
UdpEchoClientHelper echoClient (csmaInterfaces.GetAddress (nCsma), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute («Интервал», TimeValue (секунды (1.0)));
echoClient.SetAttribute ("Размер пакета", UintegerValue (1024));
ApplicationContainer clientApps =
echoClient.Install(wifiStaNodes.Get (nWifi - 1));
clientApps.Start (секунды (2.0));
clientApps.Stop (секунды (10.0));
Поскольку мы построили здесь объединенную сеть, нам необходимо включить межсетевую маршрутизацию точно так же, как
мы сделали в второй.cc пример сценария.
Ipv4GlobalRoutingHelper :: PopulateRoutingTables ();
Некоторых пользователей может удивить то, что только что созданная симуляция
никогда не остановится «естественно». Это потому, что мы попросили точку беспроводного доступа
генерировать маяки. Он будет генерировать маяки навсегда, и это приведет к тому, что симулятор
события планируются в будущем на неопределенное время, поэтому мы должны сказать симулятору, чтобы он остановился
даже если в нем могут быть запланированы события генерации радиомаяков. Следующая строка кода
говорит симулятору остановиться, чтобы мы не симулировали маяки навсегда и не вводили то, что
по сути бесконечный цикл.
Симулятор :: Стоп (Секунды (10.0));
Мы создаем трассировку, достаточную для покрытия всех трех сетей:
pointToPoint.EnablePcapAll («третий»);
phy.EnablePcap («третий», apDevices.Get (0));
csma.EnablePcap ("третий", csmaDevices.Get (0), истина);
Эти три строки кода запустят трассировку pcap на обоих двухточечных узлах, которые
служит нашей магистралью, запустит трассировку беспорядочного (мониторингового) режима в сети Wi-Fi,
и запустит беспорядочную трассировку в сети CSMA. Это позволит нам увидеть все
трафик с минимальным количеством файлов трассировки.
Наконец, мы фактически запускаем моделирование, очищаем и выходим из программы.
Симулятор :: Беги ();
Симулятор :: Уничтожить ();
0 вернуться;
}
Чтобы запустить этот пример, вам нужно скопировать Third.cc пример сценария в
рабочий каталог и используйте Waf для сборки так же, как вы это делали с второй.cc пример. если ты
находятся в каталоге верхнего уровня репозитория, который вы должны ввести,
$ cp examples / tutorial / third.cc scratch / migird.cc
$ ./ваф
$ ./waf - запустить царапину / мифирд
Опять же, поскольку мы настроили эхо-приложения UDP так же, как в второй.cc
скрипт, вы увидите аналогичный результат.
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone / ns-3-dev / build '
'build' успешно завершена (0.407 с)
За время 2 с клиент отправил 1024 байта на порт 10.1.2.4 9.
В момент времени 2.01796s сервер получил 1024 байта с порта 10.1.3.3 49153.
В момент времени 2.01796s сервер отправил 1024 байта на порт 10.1.3.3 49153
В момент времени 2.03364s клиент получил 1024 байта с порта 10.1.2.4 9.
Напомним, что первое сообщение, Отправлено 1024 байт в 10.1.2.4, "- эхо-клиент UDP
отправка пакета на сервер. В этом случае клиент находится в беспроводной сети.
(10.1.3.0). Второе сообщение "Полученный 1024 байт от 10.1.3.3, "из эха UDP
сервер, генерируемый при получении эхо-пакета. Последнее сообщение "Полученный 1024
байт от 10.1.2.4, "поступает от эхо-клиента, что указывает на то, что он получил свой эхо-сигнал.
обратно с сервера.
Если вы теперь пойдете и посмотрите в каталог верхнего уровня, вы найдете четыре файла трассировки из
это моделирование, два из нулевого узла и два из первого узла:
third-0-0.pcap third-0-1.pcap third-1-0.pcap third-1-1.pcap
Файл "third-0-0.pcap" соответствует устройству точка-точка на нулевом узле -
левая часть «позвоночника». Файл "third-1-0.pcap" соответствует двухточечной
устройство на первом узле - правая часть «магистрали». Файл "third-0-1.pcap" будет
неразборчивый (режим монитора) след от сети Wifi и файл "third-1-1.pcap"
будет беспорядочным следом из сети CSMA. Можете ли вы убедиться в этом, проверив
код?
Поскольку эхо-клиент находится в сети Wi-Fi, давайте начнем с него. Давайте посмотрим на
беспорядочная (в режиме мониторинга) трассировка, которую мы зафиксировали в этой сети.
$ tcpdump -nn -tt -r третий-0-1.pcap
Вы должны увидеть контент, похожий на Wi-Fi, которого вы здесь раньше не видели:
чтение из файла third-0-1.pcap, линк-тип IEEE802_11 (802.11)
0.000025 Маяк (ns-3-ssid) [6.0 * 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Мбит] IBSS
0.000308 Assoc Request (ns-3-ssid) [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Мбит]
0.000324 Acknowledgment RA:00:00:00:00:00:08
0.000402 Ответ Assoc AID(0) :: Успешно
0.000546 Acknowledgment RA:00:00:00:00:00:0a
0.000721 Assoc Request (ns-3-ssid) [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Мбит]
0.000737 Acknowledgment RA:00:00:00:00:00:07
0.000824 Ответ Assoc AID(0) :: Успешно
0.000968 Acknowledgment RA:00:00:00:00:00:0a
0.001134 Assoc Request (ns-3-ssid) [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Мбит]
0.001150 Acknowledgment RA:00:00:00:00:00:09
0.001273 Ответ Assoc AID(0) :: Успешно
0.001417 Acknowledgment RA:00:00:00:00:00:0a
0.102400 Маяк (ns-3-ssid) [6.0 * 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Мбит] IBSS
0.204800 Маяк (ns-3-ssid) [6.0 * 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Мбит] IBSS
0.307200 Маяк (ns-3-ssid) [6.0 * 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Мбит] IBSS
Вы можете видеть, что тип канала теперь 802.11, как и следовало ожидать. Вы, наверное, можете
понять, что происходит, и найти в этом эхо-запросе и ответных пакетах IP
след. Мы оставляем это как упражнение, чтобы полностью разобрать дамп трассировки.
Теперь посмотрите на файл pcap справа от ссылки точка-точка,
$ tcpdump -nn -tt -r третий-0-0.pcap
Опять же, вы должны увидеть знакомое содержимое:
чтение из файла third-0-0.pcap, канальный PPP (PPP)
2.008151 IP 10.1.3.3.49153> 10.1.2.4.9: UDP, длина 1024
2.026758 IP 10.1.2.4.9> 10.1.3.3.49153: UDP, длина 1024
Это эхо-пакет, идущий слева направо (от Wi-Fi к CSMA) и обратно через
связь точка-точка.
Теперь посмотрите на файл pcap справа от ссылки точка-точка,
$ tcpdump -nn -tt -r третий-1-0.pcap
Опять же, вы должны увидеть знакомое содержимое:
чтение из файла third-1-0.pcap, канальный PPP (PPP)
2.011837 IP 10.1.3.3.49153> 10.1.2.4.9: UDP, длина 1024
2.023072 IP 10.1.2.4.9> 10.1.3.3.49153: UDP, длина 1024
Это также эхо-пакет, идущий слева направо (от Wi-Fi к CSMA) и обратно.
по двухточечной ссылке с немного разными временами, как и следовало ожидать.
Эхо-сервер находится в сети CSMA, давайте посмотрим на беспорядочную трассировку там:
$ tcpdump -nn -tt -r третий-1-1.pcap
Вы должны увидеть знакомое содержимое:
чтение из файла third-1-1.pcap, линк-тип EN10MB (Ethernet)
2.017837 ARP, запрос у кого-есть 10.1.2.4 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.1, длина 50
2.017861 ARP, ответ 10.1.2.4 - в 00: 00: 00: 00: 00: 06, длина 50
2.017861 IP 10.1.3.3.49153> 10.1.2.4.9: UDP, длина 1024
2.022966 ARP, запрос у кого-есть 10.1.2.1 (ff: ff: ff: ff: ff: ff) скажите 10.1.2.4, длина 50
2.022966 ARP, ответ 10.1.2.1 - в 00: 00: 00: 00: 00: 03, длина 50
2.023072 IP 10.1.2.4.9> 10.1.3.3.49153: UDP, длина 1024
Это должно быть легко понять. Если вы забыли, вернитесь и посмотрите обсуждение
in второй.cc. Это та же последовательность.
Теперь мы потратили много времени на настройку моделей мобильности для беспроводной сети, и поэтому
было бы стыдно заканчивать, даже не показывая, что узлы STA действительно движутся
во время симуляции. Давайте сделаем это, подключив МобильностьМодель курс
изменить источник трассировки. Это всего лишь беглый взгляд на подробный раздел трассировки, который
приближается, но это кажется очень хорошим местом для примера.
Как упоминалось в разделе «Настройка ns-3», нс-3 система слежения делится на след
источников и приемников трассировки, и мы предоставляем функции для их соединения. Мы будем использовать
Предопределенный в модели мобильности источник трассировки изменения курса для инициирования событий трассировки. Мы
потребуется написать приемник трассировки для подключения к этому источнику, который будет отображать довольно
информация для нас. Несмотря на свою репутацию сложной, на самом деле это довольно просто.
Незадолго до основной программы царапина / мифирд.cc сценарий (т. е. сразу после
NS_LOG_COMPONENT_DEFINE оператор) добавьте следующую функцию:
аннулировать
CourseChange (std :: string context, Ptr модель)
{
Положение вектора = модель-> GetPosition ();
NS_LOG_UNCOND (контекст <
"x =" << position.x << ", y =" << position.y);
}
Этот код просто извлекает информацию о местоположении из модели мобильности и безоговорочно
регистрирует координаты x и y узла. Мы собираемся сделать так, чтобы эта функция была
вызывается каждый раз, когда беспроводной узел с эхо-клиентом меняет свое положение. Мы делаем это
используя Конфиг :: Подключиться функция. Просто добавьте в скрипт следующие строки кода:
до Симулятор :: Беги вызов.
std :: ostringstream oss;
oss <
"/ NodeList /" << wifiStaNodes.Get (nWifi - 1) -> GetId () <
"/ $ ns3 :: MobilityModel / CourseChange";
Config :: Connect (oss.str (), MakeCallback (& CourseChange));
Что мы делаем здесь, так это создаем строку, содержащую путь пространства имен трассировки для события.
к которому мы хотим подключиться. Во-первых, мы должны выяснить, какой именно узел мы хотим использовать.
GetId метод, как описано ранее. В случае номера по умолчанию CSMA и
беспроводных узлов, это оказывается седьмой узел и путь пространства имен трассировки к
модель мобильности будет выглядеть,
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange
Основываясь на обсуждении в разделе трассировки, вы можете сделать вывод, что этот путь трассировки
ссылается на седьмой узел в глобальном списке узлов. Он определяет то, что называется
агрегированный объект типа ns3 :: MobilityModel. Префикс знака доллара означает, что
MobilityModel агрегируется до седьмого узла. Последний компонент пути означает, что мы
подключаются к событию CourseChange этой модели.
Мы устанавливаем соединение между источником трассировки в седьмом узле и нашим приемником трассировки, вызывая
Конфиг :: Подключиться и передать этот путь к пространству имен. Как только это будет сделано, каждое изменение курса
событие на седьмом узле будет подключено к нашему приемнику трассировки, который, в свою очередь, распечатает
Новая позиция.
Если вы сейчас запустите моделирование, вы увидите, как изменения курса отображаются по мере их появления.
'build' успешно завершена (5.989 с)
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 10, y = 0
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 10.3841, y = 0.923277
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 10.2049, y = 1.90708
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 10.8136, y = 1.11368
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 10.8452, y = 2.11318
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 10.9797, y = 3.10409
За время 2 с клиент отправил 1024 байта на порт 10.1.2.4 9.
В момент времени 2.01796s сервер получил 1024 байта с порта 10.1.3.3 49153.
В момент времени 2.01796s сервер отправил 1024 байта на порт 10.1.3.3 49153
В момент времени 2.03364s клиент получил 1024 байта с порта 10.1.2.4 9.
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 11.3273, y = 4.04175
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 12.013, y = 4.76955
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 12.4317, y = 5.67771
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 11.4607, y = 5.91681
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 12.0155, y = 6.74878
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 13.0076, y = 6.62336
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 12.6285, y = 5.698
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 13.32, y = 4.97559
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 13.1134, y = 3.99715
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 13.8359, y = 4.68851
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 13.5953, y = 3.71789
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 12.7595, y = 4.26688
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 11.7629, y = 4.34913
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 11.2292, y = 5.19485
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 10.2344, y = 5.09394
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 9.3601, y = 4.60846
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 8.40025, y = 4.32795
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 9.14292, y = 4.99761
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 9.08299, y = 5.99581
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 8.26068, y = 5.42677
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 8.35917, y = 6.42191
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 7.66805, y = 7.14466
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 6.71414, y = 6.84456
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 6.42489, y = 7.80181
ОТСЛЕЖИВАНИЕ
проверка данных
Как упоминалось в UsingTracingSystem, весь смысл запуска нс-3 симуляция заключается в
генерировать выходные данные для изучения. У вас есть две основные стратегии для получения результатов от нс-3:
использование общих предопределенных механизмов массового вывода и анализ их содержимого для извлечения
интересная информация; или как-то разработать механизм вывода, который точно передает
(и, возможно, единственная) требуемая информация.
Преимущество использования предварительно определенных механизмов массового вывода состоит в том, что не требуется никаких изменений в
нс-3, но может потребоваться написание сценариев для анализа и фильтрации интересующих данных. Часто,
PCAP или НС_ЛОГ выходные сообщения собираются во время моделирования и запускаются отдельно
через скрипты, использующие GREP, СЕПГ or AWK анализировать сообщения и уменьшать и преобразовывать
данные в управляемую форму. Программы должны быть написаны для преобразования, так что это
не приходит бесплатно. НС_ЛОГ выход не считается частью нс-3 API, а может
менять без предупреждения между выпусками. Кроме того, НС_ЛОГ вывод доступен только в
отладочная сборка, поэтому использование ее снижает производительность. Конечно, если
интересующей информации нет ни в одном из предопределенных механизмов вывода, это
подход не удается.
Если вам нужно добавить некоторую лакомую информацию к заранее определенным массовым механизмам, это может
обязательно будет сделано; и если вы используете один из нс-3 механизмы, вы можете добавить свой код
в качестве вклада.
нс-3 предоставляет другой механизм, называемый трассировкой, который позволяет избежать некоторых проблем, присущих
в механизмах массового вывода. У него есть несколько важных преимуществ. Во-первых, вы можете
уменьшить объем данных, которыми вы должны управлять, отслеживая только интересующие вас события
(для больших симуляций сброс всего на диск для постобработки может создать ввод / вывод
узкие места). Во-вторых, если вы используете этот метод, вы можете контролировать формат вывода
напрямую, чтобы избежать этапа постобработки с СЕПГ, AWK, Perl or питон скрипты. Если
по вашему желанию, ваш вывод может быть отформатирован непосредственно в форму, приемлемую для gnuplot, для
пример (см. также GnuplotHelper). Вы можете добавить крючки в ядро, которые затем можно будет
к ним имеют доступ другие пользователи, но которые не будут предоставлять никакой информации, если явно не попросят
Сделай так. По этим причинам мы считаем, что нс-3 система отслеживания - лучший способ получить
информация из моделирования и, следовательно, является одним из наиболее важных механизмов
понимать в нс-3.
туповатый инструменты
Есть много способов получить информацию из программы. Самый простой способ -
чтобы просто распечатать информацию прямо на стандартный вывод, как в:
#включать
...
аннулировать
SomeFunction (недействительно)
{
uint32_t x = НЕКОТОРЫЕ_ИНТЕРЕСТИНГОВОЕ_ЗНАЧЕНИЕ;
...
std :: cout << "Значение x равно" << x << std :: endl;
...
}
Никто не помешает вам погрузиться в самую суть нс-3 и добавляем печать
заявления. Это безумно легко сделать, и, в конце концов, вы полностью контролируете свои
собственный нс-3 филиал. Это, вероятно, не будет очень удовлетворительным в долгосрочной перспективе.
срок, правда.
По мере увеличения количества операторов печати в ваших программах задача работы с
большое количество выходов будет усложняться. В конце концов, вы можете почувствовать
необходимость каким-либо образом контролировать, какая информация печатается, возможно, путем включения
и от определенных категорий отпечатков, или увеличение или уменьшение количества
информация, которую вы хотите. Если вы продолжите идти по этому пути, вы можете обнаружить, что у вас
повторно реализовал НС_ЛОГ механизм (см. UsingLogging). Чтобы этого избежать, один из
первое, что вы могли бы подумать, это использовать НС_ЛОГ себя.
Мы упоминали выше, что один из способов получить информацию из нс-3 состоит в том, чтобы проанализировать существующие НС_ЛОГ
вывод для интересной информации. Если вы обнаружите, что какую-то лакомую информацию вы
необходимости нет в существующем выводе журнала, вы можете отредактировать ядро нс-3 и просто добавьте
вашу интересную информацию в выходной поток. Теперь это определенно лучше, чем
добавление ваших собственных операторов печати, так как это следует нс-3 соглашения о кодировании и мог
потенциально может быть полезен другим людям как заплатка к существующему ядру.
Возьмем случайный пример. Если вы хотите добавить больше журналов в нс-3 Сокет TCP
(TCP-сокет-base.cc) вы можете просто добавить новое сообщение в реализацию. Уведомление
, что в TcpSocketBase :: ReceivedAck () нет сообщения журнала для случая отсутствия ACK. Ты
можно просто добавить один, изменив код. Вот оригинал:
/ ** Обработка вновь полученного ACK * /
аннулировать
TcpSocketBase :: ReceivedAck (Ptr пакет, const TcpHeader и tcpHeader)
{
NS_LOG_FUNCTION (this << tcpHeader);
// Получено ACK. Сравните номер ACK с наивысшим значением seqno без упаковки.
если (0 == (tcpHeader.GetFlags () & TcpHeader :: ACK))
{// Игнорировать, если нет флага ACK
}
...
Чтобы зарегистрировать случай отсутствия ACK, вы можете добавить новый NS_LOG_LOGIC в if тело заявления:
/ ** Обработка вновь полученного ACK * /
аннулировать
TcpSocketBase :: ReceivedAck (Ptr пакет, const TcpHeader и tcpHeader)
{
NS_LOG_FUNCTION (this << tcpHeader);
// Получено ACK. Сравните номер ACK с наивысшим значением seqno без упаковки.
если (0 == (tcpHeader.GetFlags () & TcpHeader :: ACK))
{// Игнорировать, если нет флага ACK
NS_LOG_LOGIC ("TcpSocketBase" << this << "без флага ACK");
}
...
На первый взгляд это может показаться довольно простым и удовлетворительным, но следует учесть следующее:
что вы будете писать код для добавления НС_ЛОГ заявления, и вам также нужно будет написать
код (как в GREP, СЕПГ or AWK скрипты), чтобы проанализировать вывод журнала, чтобы изолировать ваш
Информация. Это потому, что даже если у вас есть некоторый контроль над тем, что выводит
система ведения журнала, у вас есть контроль только до уровня компонентов журнала, который обычно
весь файл исходного кода.
Если вы добавляете код в существующий модуль, вам также придется жить с выводом
что любой другой разработчик нашел интересным. Вы можете обнаружить это, чтобы получить
небольшой объем информации, который вам нужен, вам, возможно, придется пробираться через огромное количество
посторонние сообщения, которые вас не интересуют. Вас могут заставить сохранить огромный журнал
файлы на диск и обрабатывать их до нескольких строк, когда вы хотите что-то сделать.
Поскольку нет никаких гарантий в нс-3 о стабильности НС_ЛОГ вывод, вы также можете
обнаружите, что части вывода журнала, от которых вы зависите, исчезают или меняются между
выпускает. Если вы зависите от структуры вывода, вы можете обнаружить, что другие сообщения
добавлены или удалены, что может повлиять на ваш код синтаксического анализа.
Наконец, НС_ЛОГ вывод доступен только в отладочных сборках, вы не можете получить вывод журнала из
оптимизированные сборки, которые выполняются примерно в два раза быстрее. Надеется НС_ЛОГ навязывает представление
штраф.
По этим причинам мы считаем, что отпечатки std :: cout и НС_ЛОГ сообщения, чтобы быть быстрыми и
грязные способы получить больше информации из нс-3, но не подходит для серьезной работы.
Желательно иметь стабильный объект, использующий стабильные API, позволяющие проникать в
ядро системы и получите только необходимую информацию. Желательно уметь делать
это без необходимости изменять и перекомпилировать основную систему. Еще лучше было бы
система, которая уведомляет код пользователя об изменении интересующего элемента или интересного события
произошло так, что пользователю не нужно активно копаться в системе в поисках
вещи.
Команда нс-3 система отслеживания предназначена для работы в этом направлении и хорошо интегрирована с
Атрибут и Конфиг подсистемы, позволяющие относительно простые сценарии использования.
Обзор
Команда нс-3 система слежения построена на концепциях независимых источников слежения и
отслеживание раковин, а также единый механизм подключения источников к раковинам.
Источники трассировки - это объекты, которые могут сигнализировать о событиях, происходящих при моделировании, и обеспечивать
доступ к интересным базовым данным. Например, источник трассировки может указывать, когда
пакет принимается сетевым устройством и обеспечивает доступ к содержимому пакета для
интересует след мойки. Источник трассировки также может указывать, когда интересное состояние
изменение происходит в модели. Например, окно перегрузки модели TCP является основным
кандидат в источник следов. Каждый раз, когда окно перегрузки меняет подключенную трассировку
раковины уведомляются со старым и новым значением.
Источники трассировки сами по себе бесполезны; они должны быть связаны с другими частями кода
которые действительно делают что-то полезное с информацией, предоставленной источником. В
объекты, которые потребляют информацию трассировки, называются приемниками трассировки. Источники следов:
генераторы данных и приемники трассировки являются потребителями. Это явное разделение допускает большие
количество источников трассировки, которые будут разбросаны по системе в местах, которые авторы модели
считаю, может быть полезно. Вставка источников трассировки приводит к очень небольшому выполнению
накладные расходы.
Может быть ноль или более потребителей событий трассировки, генерируемых источником трассировки. Можно
Считайте источник трассировки своего рода информационным каналом многоточечного соединения. Ваш код
поиск событий трассировки из определенного фрагмента основного кода может успешно сосуществовать с
другой код делает что-то совершенно отличное от той же информации.
Пока пользователь не подключит приемник трассировки к одному из этих источников, ничего не выводится. Используя
система отслеживания, и вы, и другие люди, подключенные к одному и тому же источнику трассировки, получаете
именно то, что они хотят, и только то, что они хотят от системы. Ни один из вас
влияние на любого другого пользователя путем изменения информации, выводимой системой. если ты
случайно добавили источник трассировки, ваша работа в качестве хорошего гражданина открытого исходного кода может позволить другим
пользователям предоставлять новые утилиты, которые, возможно, в целом очень полезны, без каких-либо
изменения в нс-3 ядро.
просто Пример
Давайте потратим несколько минут и рассмотрим простой пример трассировки. Нам понадобится
немного предыстории обратных вызовов, чтобы понять, что происходит в примере, поэтому мы
нужно сразу сделать небольшой объезд.
Обратные вызовы
Цель системы обратного звонка в нс-3 позволяет одному фрагменту кода вызывать функцию
(или метод в C ++) без какой-либо конкретной межмодульной зависимости. В конечном итоге это означает
вам нужно какое-то косвенное обращение - вы рассматриваете адрес вызываемой функции как
Переменная. Эта переменная называется переменной указателя на функцию. Отношения
между функцией и указателем на функцию действительно не отличается от объекта и
указатель на объект.
В C каноническим примером указателя на функцию является
указатель на возвращаемое целое число (PFI). Для PFI, принимающего один Int параметр, это
можно было объявить как,
int (* pfi) (int arg) = 0;
(Но прочтите C ++ - FAQ Раздел 33 перед написанием такого кода!) Что вы получите от этого
это переменная, названная просто PFI который инициализируется значением 0. Если вы хотите
инициализировать этот указатель на что-то значимое, у вас должна быть функция с
соответствующая подпись. В этом случае вы можете предоставить функцию, которая выглядит так:
int MyFunction (целый аргумент) {}
Если у вас есть эта цель, вы можете инициализировать переменную, чтобы она указывала на вашу функцию:
pfi = МояФункция;
Затем вы можете вызвать MyFunction косвенно, используя более понятную форму вызова:
int результат = (* pfi) (1234);
Это наводит на размышления, поскольку похоже, что вы просто разыменовываете указатель на функцию.
как если бы вы разыменовали любой указатель. Однако обычно люди пользуются
тот факт, что компилятор знает, что происходит, и просто будет использовать более короткую форму:
int результат = pfi (1234);
Похоже, вы вызываете функцию с именем PFI, но компилятор достаточно умен, чтобы
знать, как позвонить через переменную PFI косвенно к функции Моя функция.
По сути, именно так работает система отслеживания. В основном след
раковина is обратный звонок. Когда приемник трассировки выражает заинтересованность в получении событий трассировки, он
добавляет себя как обратный вызов в список обратных вызовов, находящихся внутри источника трассировки.
Когда происходит интересное событие, источник трассировки вызывает свой оператор (...) обеспечение
ноль или более аргументов. В оператор (...) в конце концов забредает в систему и
делает что-то очень похожее на непрямой вызов, который вы только что видели, обеспечивая ноль или более
параметры, как и вызов PFI выше передал один параметр целевой функции
Моя функция.
Важное отличие, которое добавляет система трассировки, заключается в том, что для каждого источника трассировки существует
это внутренний список обратных вызовов. Вместо того, чтобы просто сделать один косвенный вызов, трассировка
источник может вызывать несколько обратных вызовов. Когда приемник следа проявляет интерес к
уведомления от источника трассировки, он в основном просто организует добавление собственной функции в
список обратных вызовов.
Если вас интересует более подробная информация о том, как это на самом деле устроено в нс-3, Чувствовать
бесплатно, чтобы просмотреть раздел обратного вызова нс-3 Руководство.
Прохождение: четвертый.cc
Мы предоставили код для реализации того, что на самом деле является простейшим примером трассировки.
что можно собрать. Вы можете найти этот код в каталоге руководств как четвертый.cc.
Пройдемся по нему:
/ * - * - Режим: C ++; c-файл-стиль: "GNU"; indent-tabs-mode: ноль; - * - * /
/*
* Эта программа является бесплатным программным обеспечением; вы можете распространять и / или изменять
* это в соответствии с условиями Стандартной общественной лицензии GNU версии 2 как
* опубликовано Free Software Foundation;
*
* Эта программа распространяется в надежде, что она будет полезной,
* но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; без даже подразумеваемой гарантии
* КОММЕРЧЕСКАЯ ЦЕННОСТЬ или ПРИГОДНОСТЬ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ. Увидеть
* Стандартная общественная лицензия GNU для получения более подробной информации.
*
* Вы должны были получить копию Стандартной общественной лицензии GNU
* вместе с этой программой; если нет, напишите в Бесплатное ПО
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, США
*/
#include "ns3 / object.h"
#include "ns3 / uinteger.h"
#include "ns3 / traced-value.h"
#include "ns3 / trace-source-accessor.h"
#включать
используя пространство имен ns3;
Большая часть этого кода должна быть вам хорошо знакома. Как уже упоминалось выше, система трассировки
активно использует системы объектов и атрибутов, поэтому вам необходимо их включить.
Первые два включают в себя явное включение деклараций для этих систем. Ты
можно использовать заголовок основного модуля, чтобы получить все сразу, но мы включаем
явно здесь, чтобы проиллюстрировать, насколько все это на самом деле просто.
Файл, трассируемое-значение.h вносит необходимые декларации для отслеживания данных, которые
подчиняется семантике значений. В общем, семантика значений просто означает, что вы можете передать
объект вокруг себя, а не передает адрес объекта. Что это все на самом деле
означает, что вы сможете отслеживать все изменения, внесенные в TracedValue, в действительно
простой способ.
Поскольку система трассировки интегрирована с атрибутами, а атрибуты работают с объектами,
должен быть нс-3 объект для источника трассировки. Следующий фрагмент кода
объявляет и определяет простой объект, с которым мы можем работать.
класс MyObject: публичный объект
{
общественности:
статический TypeId GetTypeId (недействительный)
{
статический TypeId tid = TypeId ("MyObject")
.SetParent (Объект :: GetTypeId ())
.AddConstructor ()
.AddTraceSource ("MyInteger",
"Целочисленное значение для отслеживания.",
MakeTraceSourceAccessor (& MyObject :: m_myInt),
"ns3 :: Traced :: Value :: Int32Callback")
;
вернуть tid;
}
МойОбъект () {}
TracedValue m_myInt;
};
Две важные строки кода, приведенные выше, относительно трассировки: .AddTraceSource
и трассируемое значение декларация m_myInt.
Команда .AddTraceSource предоставляет "крючки", используемые для подключения источника трассировки к
внешний мир через систему Config. Первый аргумент - это имя этой трассы.
source, что делает его видимым в системе Config. Второй аргумент - это справочная строка.
Теперь посмотрим на третий аргумент, на самом деле сосредоточьтесь на аргумент третьего аргумента:
& MyObject :: m_myInt. Это TracedValue, добавляемая к классу; это
всегда член данных класса. (Последний аргумент - это имя ЬурейеЕ для
Тип TracedValue в виде строки. Это используется для создания документации для правильного
Сигнатура функции обратного вызова, которая особенно полезна для более общих типов
Обратные вызовы.)
Команда TracedValue <> объявление предоставляет инфраструктуру, которая управляет обратным вызовом
процесс. Каждый раз, когда базовое значение изменяется, механизм TracedValue предоставляет
как старое, так и новое значение этой переменной, в данном случае int32_t ценность. След
функции приемника для этого TracedValue потребуется подпись
void (* TracedValueCallback) (const int32_t oldValue, const int32_t newValue);
Все приемники трассировки, подключенные к этому источнику трассировки, должны иметь эту сигнатуру. Мы обсудим ниже
как вы можете определить необходимую подпись обратного вызова в других случаях.
Конечно, продолжая четвертый.cc мы видим:
аннулировать
IntTrace (int32_t старое значение, int32_t новое значение)
{
std :: cout << "Traced" << oldValue << "to" << newValue << std :: endl;
}
Это определение подходящего приемника трассировки. Он напрямую соответствует обратному вызову
подпись функции. После подключения эта функция будет вызываться всякий раз, когда
трассируемое значение изменений.
Теперь мы увидели источник трассировки и приемник трассировки. Остается код для подключения
источник в раковину, что происходит в main:
Int
main (int argc, char * argv [])
{
Ptr myObject = CreateObject ();
myObject-> TraceConnectWithoutContext ("MyInteger", MakeCallback (& IntTrace));
myObject-> m_myInt = 1234;
}
Здесь мы сначала создаем экземпляр MyObject, в котором находится источник трассировки.
Следующий шаг, Трассеконнектвисаутконтекст, образует связь между следом
источник и приемник трассировки. Первый аргумент - это просто имя источника трассировки MyInteger.
мы видели выше. Обратите внимание на Обратный звонок шаблонная функция. Эта функция творит чудеса
требуется для создания базового нс-3 Объект обратного вызова и свяжите его с функцией
ИнтТрейс. ТрейсКоннект связывает предоставленную вами функцию и
перегруженный Оператор () в отслеживаемой переменной, на которую ссылается атрибут "MyInteger".
После того, как эта ассоциация будет установлена, источник трассировки «активирует» предоставленный вами обратный вызов.
функции.
Код, чтобы все это произошло, конечно, нетривиальный, но суть в том, что
вы устраиваете что-то похожее на pfi () пример выше, чтобы называться
по источнику трассировки. Декларация TracedValue m_myInt; в объекте
сам выполняет магию, необходимую для предоставления перегруженных операторов присваивания, которые будут
использовать Оператор () чтобы фактически вызвать обратный вызов с желаемыми параметрами. В
.AddTraceSource выполняет магию для подключения обратного вызова к системе конфигурации, и
Трассеконнектвисаутконтекст выполняет магию, чтобы связать вашу функцию с трассировкой
источник, который определяется именем атрибута.
Давайте пока проигнорируем немного о контексте.
Наконец, строка, присваивающая значение m_myInt:
myObject-> m_myInt = 1234;
следует интерпретировать как обращение к оператор = на переменной-члене m_myInt
целое число 1234 передается как параметр.
С m_myInt - это трассируемое значение, этот оператор определен для выполнения обратного вызова, который
возвращает void и принимает в качестве параметров два целых значения --- старое значение и новое значение
для рассматриваемого целого числа. Это и есть сигнатура функции обратного вызова.
функция, которую мы предоставили --- ИнтТрейс.
Подводя итог, можно сказать, что источник трассировки - это, по сути, переменная, содержащая список обратных вызовов. А
приемник трассировки - это функция, используемая в качестве цели обратного вызова. Атрибут и тип объекта
информационные системы используются для обеспечения способа подключения источников трассировки к приемникам трассировки.
Действие "попадания" в источник трассировки - это выполнение оператора над источником трассировки, который
запускает обратные вызовы. Это приводит к обратным вызовам приемника трассировки, которые регистрируют интерес к
источник вызывается с параметрами, предоставленными источником.
Если вы сейчас соберете и запустите этот пример,
$ ./waf - запустить четвертый
вы увидите результат ИнтТрейс функция выполняется, как только источник трассировки
хит:
Прослеживается от 0 до 1234
Когда мы выполнили код, myObject-> m_myInt = 1234;, источник трассировки сработал и
автоматически предоставляет значения до и после в приемник трассировки. Функция
ИнтТрейс затем распечатайте это на стандартный вывод.
Связаться Конфиг
Команда Трассеконнектвисаутконтекст вызов, показанный выше в простом примере, на самом деле очень
редко используется в системе. Чаще Конфиг подсистема используется для выбора трассы
источник в системе, используя то, что называется Конфиг путь. Мы видели пример этого в
предыдущий раздел, в котором мы подключили событие "CourseChange", когда экспериментировали с
Third.cc.
Напомним, что мы определили приемник трассировки для вывода информации об изменении курса из мобильного устройства.
модели нашей симуляции. Теперь вам должно быть намного понятнее, что это за функция.
делать:
аннулировать
CourseChange (std :: string context, Ptr модель)
{
Положение вектора = модель-> GetPosition ();
NS_LOG_UNCOND (контекст <
"x =" << position.x << ", y =" << position.y);
}
Когда мы соединили источник трассировки "CourseChange" с указанным выше приемником трассировки, мы использовали
Путь к конфигурации, чтобы указать источник, когда мы установили соединение между предварительно определенными
источник трассировки и новый приемник трассировки:
std :: ostringstream oss;
oss << "/ NodeList /"
<< wifiStaNodes.Get (nWifi - 1) -> GetId ()
<< "/ $ ns3 :: MobilityModel / CourseChange";
Config :: Connect (oss.str (), MakeCallback (& CourseChange));
Давайте попробуем разобраться в том, что иногда считается относительно загадочным кодом.
В целях обсуждения предположим, что номер узла, возвращенный GetId () is
«7». В этом случае указанный выше путь оказывается
"/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange"
Последний сегмент пути конфигурации должен быть Атрибут из объект. На самом деле, если бы у вас
указатель на объект который имеет "CourseChange" Атрибут удобно, вы могли бы написать это
точно так же, как мы сделали в предыдущем примере. Вы уже знаете, что мы обычно храним
указатели на наши Nodes в NodeContainer. в Third.cc Например, интересующие узлы
хранятся в Wi-FiStaNodes NodeContainer. Фактически, прокладывая путь,
мы использовали этот контейнер, чтобы получить Ptr который мы называли GetId (). Мы могли бы иметь
использовал это Ptr для прямого вызова метода Connect:
Ptr theObject = wifiStaNodes.Get (nWifi - 1);
theObject-> TraceConnectWithoutContext ("CourseChange", MakeCallback (& CourseChange));
В Third.cc Например, мы действительно хотели, чтобы вместе с
с параметрами обратного вызова (которые будут объяснены ниже), чтобы мы могли фактически использовать
следующий эквивалентный код:
Ptr theObject = wifiStaNodes.Get (nWifi - 1);
theObject-> TraceConnect ("CourseChange", MakeCallback (& CourseChange));
Оказывается, внутренний код для Config :: ConnectWithoutContext и Конфиг :: Подключиться
на самом деле найти Ptr и позвонить в соответствующий ТрейсКоннект метод на самом низком уровне
уровень.
Команда Конфиг функции идут по пути, который представляет собой цепочку объект указатели. Каждый сегмент
пути соответствует атрибуту объекта. Последний сегмент - это Атрибут
Интерес, и предыдущие сегменты должны быть напечатаны, чтобы содержать или находить объекты. В Конфиг код
анализирует и "обходит" этот путь, пока не дойдет до последнего сегмента пути. Тогда это
интерпретирует последний сегмент как Атрибут на последнем объекте, найденном во время прогулки по
дорожка. В Конфиг функции затем вызывают соответствующие ТрейсКоннект or
Трассеконнектвисаутконтекст на финальном объекте. Посмотрим, что будет дальше
более подробно, когда пройден вышеуказанный путь.
Начальный символ «/» в пути относится к так называемому пространству имен. Один из
предопределенным пространством имен в системе конфигурации является «NodeList», который представляет собой список всех
узлов в моделировании. Элементы в списке упоминаются индексами в списке, поэтому
«/ NodeList / 7» относится к восьмому узлу в списке узлов, созданных во время моделирования.
(индексы отзыва начинаются с 0 '). Эти ссылка is на самом деле a `` Птр ` и так
подкласс ns3 :: Объект.
Как описано в разделе "Объектная модель" нс-3 Руководство, мы широко используем
агрегирование объектов. Это позволяет нам формировать ассоциацию между разными объектами.
без построения сложного дерева наследования или предопределения, какие объекты будут частью
узла. К каждому объекту в агрегации можно получить доступ из других объектов.
В нашем примере следующий пройденный сегмент пути начинается с символа «$». Этот
указывает системе конфигурации, что сегмент является именем типа объекта, поэтому
ПолучитьОбъект вызов должен быть сделан в поисках этого типа. Получается, что Мобильность
используется в Third.cc организует агрегирование или связывание модели мобильности с каждым из
беспроводной Nodes. Когда вы добавляете «$», вы запрашиваете другой объект, у которого есть
предположительно ранее были агрегированы. Вы можете думать об этом как о указателях переключения из
оригинальный Ptr как указано в "/ NodeList / 7" связанной с ним модели мобильности ---
который имеет тип ns3 :: MobilityModel. Если вы знакомы с ПолучитьОбъект, мы спросили
система должна сделать следующее:
Ptr MobilityModel = узел-> GetObject ()
Теперь мы на последнем объекте на пути, поэтому обратим внимание на атрибуты
этот объект. В МобильностьМодель Класс определяет атрибут под названием «CourseChange». Ты сможешь
увидеть это, посмотрев исходный код в SRC / мобильность / модель / мобильность-model.cc и
поиск "CourseChange" в вашем любимом редакторе. Ты должен найти
.AddTraceSource ("CourseChange",
«Значение вектора положения и / или скорости изменено»,
MakeTraceSourceAccessor (& MobilityModel :: m_courseChangeTrace),
"ns3 :: MobilityModel :: CourseChangeCallback")
который на данный момент должен показаться очень знакомым.
Если вы ищете соответствующее объявление базовой отслеживаемой переменной в
мобильность-модель.h Вы найдете
TracedCallback > m_courseChangeTrace;
Объявление типа Трассированный обратный вызов идентифицирует m_courseChangeTrace как специальный список
Обратные вызовы, которые могут быть перехвачены с помощью функций конфигурации, описанных выше. В ЬурейеЕ для
подпись функции обратного вызова также определена в файле заголовка:
typedef void (* CourseChangeCallback) (Ptr * модель);
Команда МобильностьМодель class разработан как базовый класс, предоставляющий общий интерфейс для
все конкретные подклассы. Если вы выполните поиск до конца файла, вы увидите
определенный метод называется NotifyCourseChange ():
аннулировать
MobilityModel :: NotifyCourseChange (void) const
{
m_courseChangeTrace (это);
}
Производные классы будут вызывать этот метод всякий раз, когда они изменяют курс для поддержки
отслеживание. Этот метод вызывает Оператор () на основе m_courseChangeTrace, который
будет, в свою очередь, вызывать все зарегистрированные обратные вызовы, вызывая все приемники трассировки, которые
зарегистрировали интерес к источнику трассировки, вызвав функцию Config.
Итак, в Third.cc пример, который мы рассмотрели, всякий раз, когда меняется курс в одном из
RandomWalk2dMobilityModel установленных экземпляров, будет NotifyCourseChange () призывают
который вызывает в МобильностьМодель базовый класс. Как видно выше, это вызывает Оператор ()
on m_courseChangeTrace, который, в свою очередь, вызывает любые зарегистрированные приемники трассировки. В этом примере
единственный код, регистрировавший интерес, был кодом, который предоставлял путь к конфигурации.
Следовательно КурсИзменить функция, которая была подключена к седьмому узлу, будет
звонил только Обратный звонок.
Последний кусок головоломки - это «контекст». Напомним, что мы видели вывод в виде
что-то вроде следующего из Third.cc:
/ NodeList / 7 / $ ns3 :: MobilityModel / CourseChange x = 7.27897, y =
2.22677
Первая часть вывода - это контекст. Это просто путь, по которому
код config обнаружил источник трассировки. В случае, который мы рассматривали, может быть
любое количество источников трассировки в системе, соответствующее любому количеству узлов с
модели мобильности. Должен быть какой-то способ определить, какой источник трассировки на самом деле
тот, который запустил Обратный вызов. Самый простой способ - связаться с Конфиг :: Подключитьсявместо
of Config :: ConnectWithoutContext.
Обнаружение Источники
Первый вопрос, который неизбежно возникает у новых пользователей системы отслеживания: "Хорошо,
I знают который там должен be прослеживать источники in моделирование ядро, но это do I найдите внешний почему
прослеживать источники доступен в я? "
Второй вопрос: "Хорошо, I найденный a прослеживать источник, это do I понять внешний Конфиг путь
в использование когда I соединяться в Это?"
Третий вопрос: "Хорошо, I найденный a прослеживать источник и Конфиг дорожка, это do I понять
внешний почему возвращают напишите и формальный Аргументы of my Перезвони функция в быть?"
Четвертый вопрос: "Хорошо, I набранный который ВСЕ in и есть этой невероятно причудливый ошибка
сообщение, почему in Мир приносит it иметь в виду?"
Мы рассмотрим каждый из них по очереди.
Доступен Источники
Хорошо, I знают который там должен be прослеживать источники in моделирование ядро, но это do I найдите
внешний почему прослеживать источники доступен в меня?
Ответ на первый вопрос находится в нс-3 Документация по API. Если вы пойдете в
сайт проекта, нс-3 Проект, вы найдете ссылку на «Документацию» в навигации
бар. Если вы выберете эту ссылку, вы попадете на нашу страницу документации. Eсть
ссылка на «Последний выпуск», которая приведет вас к документации по последней стабильной версии.
релиз нс-3. Если вы выберете ссылку «Документация по API», вы попадете в
нс-3 Страница документации API.
На боковой панели вы должны увидеть иерархию, которая начинается
· Нс-3
· Документация нс-3
· Все источники трассировки
· Все атрибуты
· Все GlobalValues
Список интересующих нас здесь - «Все источники трассировки». Идите вперед и выберите эту ссылку.
Вы увидите, что, возможно, не слишком удивительно, список всех доступных источников трассировки.
in нс-3.
В качестве примера прокрутите вниз до ns3 :: MobilityModel. Вы найдете запись для
CourseChange: значение вектора положения и / или скорости изменено.
Вы должны распознать это как источник трассировки, который мы использовали в Third.cc пример. Просматривая
этот список будет вам полезен.
Конфиг Пути
Хорошо, I найденный a прослеживать источник, это do I понять внешний Конфиг путь в использование когда I соединяться в
Это?
Если вы знаете, какой объект вас интересует, раздел «Подробное описание» для
class перечислит все доступные источники трассировки. Например, начиная со списка «Все
TraceSources "нажмите на ns3 :: MobilityModel ссылка, которая приведет вас к
документация для МобильностьМодель класс. Практически вверху страницы - однострочная
краткое описание класса, оканчивающееся ссылкой «Подробнее ...». Нажмите на эту ссылку, чтобы пропустить
сводку API и перейдите к «Подробному описанию» класса. В конце
описание будет (до) трех списков:
· Конфиг Пути: список типичных путей конфигурации для этого класса.
· Атрибуты: список всех атрибутов, предоставляемых этим классом.
· Источники трассировки: список всех источников трассировки, доступных в этом классе.
Сначала мы обсудим пути конфигурации.
Предположим, вы только что нашли источник трассировки «CourseChange» в «Все
TraceSources ", и вы хотите выяснить, как к нему подключиться. Вы знаете, что вы
используя (опять же, из Third.cc пример) ns3 :: RandomWalk2dMobilityModel. Так что либо
щелкните имя класса в списке «Все источники трассировки» или найдите
ns3 :: RandomWalk2dMobilityModel в «Списке классов». В любом случае теперь вы должны искать
на странице «Описание класса ns3 :: RandomWalk2dMobilityModel».
Если теперь прокрутить вниз до раздела «Подробное описание» после сводного списка
методы и атрибуты класса (или просто нажмите ссылку "Подробнее ..." в конце класса
краткое описание вверху страницы) вы увидите полную документацию по
класс. Продолжая прокручивать вниз, найдите список «Пути конфигурации»:
Конфиг Пути
ns3 :: RandomWalk2dMobilityModel доступен по следующим путям с
Конфиг :: Установить и Конфиг :: Подключиться:
· "/ NodeList / [i] / $ ns3 :: MobilityModel / $ ns3 :: RandomWalk2dMobilityModel"
В документации рассказывается, как добраться до RandomWalk2dMobilityModel Объект. Сравнивать
строка выше со строкой, которую мы фактически использовали в примере кода:
"/ NodeList / 7 / $ ns3 :: MobilityModel"
Разница связана с тем, что два ПолучитьОбъект вызовы подразумеваются в найденной строке
в документации. Первый, для $ ns3 :: MobilityModel запросит агрегирование для
базовый класс. Второй подразумевается ПолучитьОбъект звать $ ns3 :: RandomWalk2dMobilityModel,
используется для приведения базового класса к конкретному классу реализации. Документация
показывает обе эти операции для вас. Оказывается, фактическим источником трассировки вы являетесь
ищет находится в базовом классе.
Список источников трассировки см. Ниже в разделе «Подробное описание».
Ты найдешь
Для этого типа не определены источники трассировки.
Источники трассировки определенный in родителя класс `` ns3 :: MobilityModel``
· КурсИзменить: Значение вектора положения и / или скорости изменено.
Подпись обратного звонка: ns3 :: MobilityModel :: CourseChangeCallback
Это именно то, что вам нужно знать. Интересующий источник трассировки находится в
ns3 :: MobilityModel (который вы все равно знали). Самое интересное в этом API
Документация сообщает вам, что вам не нужно это дополнительное приведение в пути конфигурации выше к
перейти к конкретному классу, поскольку источник трассировки фактически находится в базовом классе.
Поэтому дополнительные ПолучитьОбъект не требуется, и вы просто используете путь:
"/ NodeList / [i] / $ ns3 :: MobilityModel"
что идеально соответствует пути примера:
"/ NodeList / 7 / $ ns3 :: MobilityModel"
Кстати, еще один способ найти путь к конфигурации - это GREP вокруг в нс-3 кодовая
для того, кто уже разобрался. Вы всегда должны пытаться скопировать чужие
рабочий код, прежде чем вы начнете писать свой собственный. Попробуйте что-нибудь вроде:
$ найти. -name '* .cc' | xargs grep CourseChange | grep Connect
и вы можете найти свой ответ вместе с рабочим кодом. Например, в этом случае
SRC / мобильность / примеры / main-random-topology.cc есть что-то, что вы только и ждете:
Config :: Connect ("/ NodeList / * / $ ns3 :: MobilityModel / CourseChange",
MakeCallback (& CourseChange));
Мы вернемся к этому примеру чуть позже.
Обратный звонок Подписи
Хорошо, I найденный a прослеживать источник и Конфиг дорожка, это do I понять внешний почему возвращают напишите
и формальный Аргументы of my Перезвони функция в быть?
Самый простой способ - проверить подпись обратного вызова ЬурейеЕ, который дан в
«Подпись обратного вызова» источника трассировки в «Подробном описании» для класса, как
показано выше.
Повторение записи источника трассировки "CourseChange" из ns3 :: RandomWalk2dMobilityModel we
иметь:
· КурсИзменить: Значение вектора положения и / или скорости изменено.
Подпись обратного звонка: ns3 :: MobilityModel :: CourseChangeCallback
Подпись обратного вызова дается как ссылка на соответствующий ЬурейеЕ, где находим
ЬурейеЕ аннулировать (* CourseChangeCallback) (const станд :: строка контекст, Ptr
МобильностьМодель> * модель);
Трассированный обратный вызов подпись для уведомлений об изменении курса.
Если обратный вызов подключен с помощью Подключить без контекста опустить контекст аргумент от
подпись.
параметры:
[in] context Строка контекста, предоставленная источником трассировки.
[in] Модель MobilityModel, меняющая курс.
Как и выше, чтобы увидеть это в использовании GREP вокруг в нс-3 кодовая база для примера. Пример
выше, из SRC / мобильность / примеры / main-random-topology.cc, подключает "CourseChange"
проследить источник до КурсИзменить функция в том же файле:
статическая пустота
CourseChange (std :: string context, Ptr модель)
{
...
}
Обратите внимание, что эта функция:
· Принимает «контекстный» строковый аргумент, который мы опишем через минуту. (Если обратный вызов
связан с помощью Подключить без контекста функционировать контекст аргумент будет
опущено.)
· Имеет МобильностьМодель предоставляется в качестве последнего аргумента (или только аргумента, если
Подключить без контекста используется).
· Возврат аннулировать.
Если случайно подпись обратного вызова не была задокументирована, и нет примеров для
работа, определение правильной сигнатуры функции обратного вызова может быть сложной задачей для
собственно выяснить из исходного кода.
Прежде чем приступить к рассмотрению кода, я буду любезен и расскажу вам простой способ
чтобы понять это: возвращаемое значение вашего обратного вызова всегда будет аннулировать, Формальный
список параметров для Трассированный обратный вызов можно найти в списке параметров шаблона в
декларация. Напомним, что в нашем текущем примере это находится в мобильность-модель.h, где мы
ранее нашли:
TracedCallback > m_courseChangeTrace;
Между списком параметров шаблона в
объявление и формальные аргументы функции обратного вызова. Здесь есть один
параметр шаблона, который является Ptr МобильностьМодель>. Это говорит вам, что вам нужен
функция, которая возвращает void и принимает Ptr МобильностьМодель>. Например:
аннулировать
CourseChange (Ptr модель)
{
...
}
Это все, что тебе нужно, если ты хочешь Config :: ConnectWithoutContext. Если вам нужен контекст,
тебе нужно Конфиг :: Подключиться и используйте функцию обратного вызова, которая принимает строковый контекст, тогда
аргументы шаблона:
аннулировать
CourseChange (const std :: string context, Ptr модель)
{
...
}
Если вы хотите убедиться, что ваш CourseChangeОбратный вызов функция видна только в вашем
локальный файл, вы можете добавить ключевое слово статический и придумали:
статическая пустота
CourseChange (const std :: string path, Ptr модель)
{
...
}
это именно то, что мы использовали в Third.cc пример.
Реализация
Этот раздел не является обязательным. Поездка будет ухабистой, особенно для тех, кто
не знаком с деталями шаблонов. Однако, если вы пройдете через это, у вас будет
очень хорошо разбирается во многих нс-3 идиомы низкого уровня.
Итак, снова давайте разберемся, какая подпись функции обратного вызова требуется для
Источник трассировки "CourseChange". Это будет болезненно, но вам нужно только это сделать
однажды. После того, как вы пройдете через это, вы сможете просто посмотреть на Трассированный обратный вызов и
понимать это.
Первое, на что нам нужно обратить внимание, это объявление источника трассировки. Напомним, что
это в мобильность-модель.h, где мы ранее нашли:
TracedCallback > m_courseChangeTrace;
Это объявление для шаблона. Параметр шаблона находится внутри угловых скобок,
так что нам действительно интересно узнать, что это TracedCallback <> является. Если у вас есть
абсолютно не знаю, где это можно найти, GREP является вашим другом.
Вероятно, нас будет интересовать какое-то объявление в нс-3 источник, так что
первое изменение в SRC каталог. Тогда мы знаем, что это объявление должно быть
быть в каком-то заголовочном файле, так что просто GREP для этого используют:
$ найти. -name '* .h' | xargs grep TracedCallback
Вы увидите, что 303 строки пролетят мимо (я пропустил это через wc чтобы увидеть, насколько это плохо). Несмотря на то что
это может показаться большим, но на самом деле это не так уж и много. Просто пропустите вывод через больше и
начать сканирование через него. На первой странице вы увидите очень подозрительно
шаблонно выглядящие вещи.
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::TracedCallback ()
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::ConnectWithoutContext (c ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::Connect (const CallbackB ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::DisconnectWithoutContext ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::Disconnect (const Callba ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (void) const ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1) const ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::operator() (T1 a1, T2 a2 ...
Оказывается, все это происходит из заголовочного файла. трассированный callback.h что звучит
очень многообещающе. Затем вы можете взглянуть на мобильность-модель.h и увидишь, что есть линия
что подтверждает эту догадку:
#include "ns3 / traced-callback.h"
Конечно, вы могли бы пойти на это с другой стороны и начать с рассмотрения
включает в мобильность-модель.h и заметив включение трассированный callback.h и
предполагая, что это должен быть тот файл, который вам нужен.
В любом случае следующий шаг - взглянуть на SRC / ядро / модель / трассировка-callback.h in
ваш любимый редактор, чтобы увидеть, что происходит.
Вы увидите комментарий вверху файла, который должен вас утешить:
Ns3 :: TracedCallback имеет почти тот же API, что и обычный ns3 :: Callback, но
вместо переадресации вызовов одной функции (как обычно делает ns3 :: Callback),
он перенаправляет вызовы в цепочку ns3 :: Callback.
Это должно звучать очень знакомо и указывать на то, что вы на правильном пути.
Сразу после этого комментария вы найдете
шаблон
имя типа T3 = пусто, имя типа T4 = пусто,
имя типа T5 = пусто, имя типа T6 = пусто,
typename T7 = пусто, typename T8 = empty>
класс TracedCallback
{
...
Это говорит о том, что TracedCallback - это шаблонный класс. Имеет восемь возможных типов
параметры со значениями по умолчанию. Вернитесь и сравните это с заявлением, которое вы
пытаясь понять:
TracedCallback > m_courseChangeTrace;
Команда имяТипа T1 в объявлении шаблонного класса соответствует Ptr
МобильностьМодель> в заявлении выше. Все остальные параметры типа оставлены как
по умолчанию. Взгляд на конструктор мало что вам скажет. Единственное место, где
вы видели, что между вашей функцией обратного вызова и системой отслеживания установлена связь.
в Связаться и Подключить без контекста функции. Если вы прокрутите вниз, вы увидите
Подключить без контекста метод здесь:
шаблон
имя типа T3, имя типа T4,
имя типа T5, имя типа T6,
имя типа T7, имя типа T8>
аннулировать
TracedCallback<T1,T2,T3,T4,T5,T6,T7,T8>::ConnectWithoutContext ...
{
Callback<void,T1,T2,T3,T4,T5,T6,T7,T8> cb;
cb.Assign (обратный вызов);
m_callbackList.push_back (кб);
}
Теперь вы во чреве зверя. Когда создается экземпляр шаблона для
объявление выше, компилятор заменит T1 Ptr МобильностьМодель>.
аннулировать
TracedCallback :: ConnectWithoutContext ... cb
{
Перезвони > cb;
cb.Assign (обратный вызов);
m_callbackList.push_back (кб);
}
Теперь вы можете увидеть реализацию всего, о чем мы говорили. Код
создает Обратный вызов правильного типа и назначает ему вашу функцию. Это
эквивалент PFI = Моя функция мы обсуждали в начале этого раздела. Код
затем добавляет обратный вызов в список обратных вызовов для этого источника. Осталось только
чтобы посмотреть определение обратного вызова. Используя тот же GREP трюк, как мы привыкли находить
Трассированный обратный вызов, вы сможете обнаружить, что файл ./ядро/обратный вызов.ч тот, кого мы
нужно посмотреть.
Если вы посмотрите в файл, вы увидите много, вероятно, почти непонятного
код шаблона. В конечном итоге вы найдете документацию по API для обратного вызова.
шаблонный класс, тем не менее. К счастью, есть немного английского:
Обратный звонок шаблонный класс.
Этот шаблон класса реализует шаблон проектирования функтора. Он используется для объявления
тип Обратный звонок:
· Первый необязательный аргумент шаблона представляет тип возвращаемого значения обратного вызова.
· Напоминающие (необязательные) аргументы шаблона представляют тип последующего
аргументы обратного вызова.
· Поддерживается до девяти аргументов.
Мы пытаемся понять, что за
Перезвони > cb;
декларация означает. Теперь мы можем понять, что первый (необязательный)
аргумент шаблона, аннулировать, представляет тип возвращаемого значения обратного вызова. Секунда
(необязательно) аргумент шаблона, Ptr МобильностьМодель> представляет собой тип первого
аргумент обратного вызова.
Рассматриваемый обратный вызов - это ваша функция для получения событий трассировки. Из этого вы можете
сделайте вывод, что вам нужна функция, которая возвращает аннулировать и берет Ptr МобильностьМодель>.
Например,
аннулировать
CourseChangeCallback (Ptr модель)
{
...
}
Это все, что тебе нужно, если ты хочешь Config :: ConnectWithoutContext. Если вам нужен контекст,
тебе нужно Конфиг :: Подключиться и используйте функцию обратного вызова, которая принимает строковый контекст. Этот
потому что Связаться функция предоставит вам контекст. Вам понадобиться:
аннулировать
CourseChangeCallback (std :: string context, Ptr модель)
{
...
}
Если вы хотите убедиться, что ваш CourseChangeОбратный вызов отображается только в вашем локальном файле,
вы можете добавить ключевое слово статический и придумали:
статическая пустота
CourseChangeCallback (std :: string path, Ptr модель)
{
...
}
это именно то, что мы использовали в Third.cc пример. Возможно, вам стоит вернуться и
перечитайте предыдущий раздел (Поверьте мне на слово).
Если вас интересует более подробная информация о реализации обратных вызовов, не стесняйтесь
взглянуть на нс-3 руководство. Это одна из наиболее часто используемых конструкций в
низкоуровневые части нс-3. Это, на мой взгляд, довольно изящная вещь.
Трассированные значения
Ранее в этом разделе мы представили простой фрагмент кода, который использовал
TracedValue чтобы продемонстрировать основы кода трассировки. Мы просто замалчивали
что такое TracedValue и как найти тип возвращаемого значения и формальные аргументы для
обратный вызов.
Как мы уже упоминали, файл, трассируемое-значение.h вносит необходимые декларации для отслеживания
данных, которые подчиняются семантике значений. В общем, семантика значений просто означает, что вы можете
передавать сам объект, а не передавать адрес объекта. Мы расширяем
это требование о включении полного набора операторов стиля присваивания, которые
предопределено для типов простых старых данных (POD):
┌──────────────────────────────────┬──────────────
│оператор = (присвоение) │ │
├──────────────────────────────────┼──────────────
│оператор * = │ оператор / = │
├──────────────────────────────────┼──────────────
│оператор + = │ оператор- = │
├──────────────────────────────────┼──────────────
│оператор ++ (оба префикса и │ │
│постфикс) │ │
├──────────────────────────────────┼──────────────
│оператор - (оба префикса и │ │
│постфикс) │ │
├──────────────────────────────────┼──────────────
│оператор << = │ оператор >> = │
├──────────────────────────────────┼──────────────
│оператор & = │ оператор | = │
├──────────────────────────────────┼──────────────
│оператор% = │ оператор ^ = │
└──────────────────────────────────┴──────────────
На самом деле все это означает, что вы сможете отслеживать все изменения, сделанные с помощью этих
к объекту C ++, имеющему семантику значений.
Команда TracedValue <> декларация, которую мы видели выше, предоставляет инфраструктуру, которая перегружает
упомянутые выше операторы и управляют процессом обратного вызова. При использовании любого из операторов
выше с трассируемое значение он предоставит как старое, так и новое значение этой переменной,
в этом случае int32_t ценность. При осмотре трассируемое значение декларация, мы знаем
функция приемника трассировки будет иметь аргументы (константа int32_t старое значение, Const int32_t новое значение).
Тип возврата для трассируемое значение функция обратного вызова всегда аннулировать, поэтому ожидаемый
подпись обратного вызова будет:
void (* TracedValueCallback) (const int32_t oldValue, const int32_t newValue);
Команда .AddTraceSource в GetTypeId метод предоставляет "крючки", используемые для подключения
проследить источник до внешнего мира через систему Config. Мы уже обсуждали
первые три агрумента ДобавитьTraceSource: имя атрибута для системы конфигурации, справка
строка и адрес члена данных класса TracedValue.
Последний строковый аргумент, «ns3 :: Traced :: Value :: Int32» в примере, - это имя
ЬурейеЕ для сигнатуры функции обратного вызова. Мы требуем, чтобы эти подписи были определены,
и дайте полное имя типа для ДобавитьTraceSource, поэтому документация по API может
связать источник трассировки с сигнатурой функции. Для TracedValue подпись
простой; для TracedCallbacks мы уже видели, как действительно помогают документы API.
Real Пример
Давайте возьмем пример, взятый из одной из самых известных книг по TCP. "TCP / IP
«Иллюстрированный том 1: Протоколы» У. Ричарда Стивенса - это классика. Я только что перевернул
книга открылась и натолкнулась на красивый сюжет как окна скопления, так и последовательности
числа в зависимости от времени на стр. 366. Стивенс называет это «Рисунок 21.10. Значение cwnd и
отправить порядковый номер во время передачи данных. "Давайте просто воссоздадим часть cwnd
этого сюжета в нс-3 используя систему отслеживания и Gnuplot.
Доступен Источники
Первое, о чем нужно подумать, - это то, как мы хотим получить данные. Что это мы
нужно отследить? Итак, давайте проконсультируемся со списком «Все источники трассировки», чтобы узнать, с чем нам нужно работать.
с участием. Напомним, что это находится в нс-3 Документация по API. Если вы пролистаете
list, вы в конечном итоге найдете:
ns3 :: TcpNewReno
· Окно перегрузки: Окно перегрузки TCP-соединения
· Порог медленного старта: Порог медленного запуска TCP (байты)
Оказывается, что нс-3 Реализация TCP живет (в основном) в файле
SRC / Интернет / модель / tcp-socket-base.cc в то время как варианты управления перегрузкой находятся в файлах, таких
as SRC / Интернет / модель / tcp-newreno.cc. Если ты этого не знаешь a априори, вы можете использовать
рекурсивный GREP обманывать:
$ найти. -name '* .cc' | xargs grep -i tcp
Вы найдете страницу за страницей экземпляров tcp, указывающих вам на этот файл.
Создание документации по классам для TcpNewReno и переход к списку
Источники трассировки вы найдете
Источники трассировки
· Окно перегрузки: Окно перегрузки TCP-соединения
Подпись обратного звонка: ns3 :: Traced :: Value :: Uint322Callback
Нажав на обратный звонок ЬурейеЕ link мы видим подпись, которую вы теперь знаете, чтобы ожидать:
typedef void (* ns3 :: Traced :: Value :: Int32Callback) (const int32_t oldValue, const int32_t newValue)
Теперь вы должны полностью понять этот код. Если у нас есть указатель на TcpNewReno,
мы можем ТрейсКоннект к источнику трассировки "CongestionWindow", если мы предоставим соответствующий
цель обратного вызова. Это тот же источник трассировки, который мы видели в простом примере.
в начале этого раздела, за исключением того, что мы говорим о uint32_t вместо
int32_t. И мы знаем, что должны предоставить функцию обратного вызова с этой подписью.
Обнаружение Примеры
Всегда лучше попытаться найти рабочий код, который вы можете изменить, скорее
чем начинать с нуля. Итак, первая задача сейчас - найти код, который
уже подключает источник трассировки "CongestionWindow" и посмотрим, сможем ли мы его изменить. Как обычно,
GREP твой друг:
$ найти. -name '* .cc' | xargs grep CongestionWindow
Это укажет на пару многообещающих кандидатов: примеры / tcp / tcp-large-transfer.cc
и SRC / тест / ns3tcp / ns3tcp-cwnd-test-suite.cc.
Мы еще не посетили ни один тестовый код, поэтому давайте взглянем туда. Ты будешь
обычно обнаруживают, что тестовый код довольно минимален, так что это, вероятно, очень хорошая ставка.
Откройте SRC / тест / ns3tcp / ns3tcp-cwnd-test-suite.cc в вашем любимом редакторе и ищите
«Окно перегрузки». Ты найдешь,
ns3TcpSocket-> TraceConnectWithoutContext ("CongestionWindow",
MakeCallback (& Ns3TcpCwndTestCase1 :: CwndChange, это));
Это должно быть вам очень знакомо. Мы упоминали выше, что если бы у нас был указатель на
TcpNewReno, мы могли бы ТрейсКоннект к источнику трассировки "CongestionWindow". Это точно
что у нас здесь; поэтому оказывается, что эта строка кода делает именно то, что мы хотим.
Давайте продолжим и извлечем нужный нам код из этой функции (Ns3TcpCwndTestCase1 :: DoRun
(пустота)). Если вы посмотрите на эту функцию, вы обнаружите, что она выглядит как нс-3
сценарий. Оказывается, это именно то, что нужно. Это сценарий, запускаемый тестом
рамки, поэтому мы можем просто вытащить его и завернуть в main вместо того, чтобы в ДоРун, Скорее
чем пройти через это, шаг за шагом, мы предоставили файл, полученный в результате переноса
этот тест обратно на родной нс-3 сценарий - примеры / учебник / Friday.cc.
Dynamic Прослеживать Источники
Команда Friday.cc пример демонстрирует чрезвычайно важное правило, которое вы должны понимать
перед использованием любого источника трассировки: вы должны убедиться, что цель
Конфиг :: Подключиться команда существует, прежде чем пытаться ее использовать. Это не что иное, как сказать
объект должен быть создан, прежде чем пытаться вызвать его. Хотя это может показаться очевидным
если заявлено таким образом, это действительно сбивает с толку многих людей, пытающихся использовать систему в первую очередь.
времени.
Вернемся на мгновение к основам. Есть три основных этапа выполнения, которые существуют в
любой нс-3 сценарий. Первый этап иногда называют «Время настройки» или «Настройка.
Время "и существует в период, когда main функция вашего скрипта запущена, но
до Симулятор :: Беги называется. Вторую фазу иногда называют «Время моделирования».
и существует в период, когда Симулятор :: Беги активно выполняет свои мероприятия.
После завершения моделирования, Симулятор :: Беги вернет управление обратно
main функция. Когда это происходит, скрипт входит в то, что можно назвать "Разборка".
Фаза », когда структуры и объекты, созданные во время настройки, разбираются и
выпущенный.
Возможно, наиболее распространенная ошибка, совершаемая при попытке использовать систему отслеживания, заключается в предположении, что
объекты, построенные динамически в течение моделирование время доступны во время настройки
время. В частности, нс-3 Розетка это динамический объект, часто создаваемый Приложения в
общаться между Nodes. нс-3 Процесс подачи заявки всегда есть «Время начала» и «Стоп».
Время ». В подавляющем большинстве случаев Процесс подачи заявки не будет пытаться
создать динамический объект до тех пор, пока его Запустить приложение метод вызывается при некотором "Старт"
Время ». Это необходимо для того, чтобы симуляция была полностью настроена до того, как приложение
пытается что-то сделать (что произойдет, если он попытается подключиться к несуществующему узлу
еще во время настройки?). В результате на этапе настройки вы не можете
подключить источник трассировки к приемнику трассировки, если один из них создается динамически во время
моделирование.
Два решения этой головоломки:
1. Создайте событие симулятора, которое запускается после создания динамического объекта, и подключите
отслеживать, когда это событие выполняется; или
2. Создайте динамический объект во время настройки, затем подключите его и передайте объект в
система для использования во время моделирования.
Мы выбрали второй подход в Friday.cc пример. Это решение потребовало от нас создания
Мое приложение Процесс подачи заявки, вся цель которого состоит в том, чтобы Розетка в качестве параметра.
Прохождение: Friday.cc
Теперь давайте посмотрим на пример программы, которую мы создали, проанализировав перегрузку.
окно тест. Открытым примеры / учебник / Friday.cc в вашем любимом редакторе. Тебе следует увидеть
какой-то знакомый код:
/ * - * - Режим: C ++; c-файл-стиль: "GNU"; indent-tabs-mode: ноль; - * - * /
/*
* Эта программа является бесплатным программным обеспечением; вы можете распространять и / или изменять
* это в соответствии с условиями Стандартной общественной лицензии GNU версии 2 как
* опубликовано Free Software Foundation;
*
* Эта программа распространяется в надежде, что она будет полезной,
* но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ; без даже подразумеваемой гарантии
* КОММЕРЧЕСКАЯ ЦЕННОСТЬ или ПРИГОДНОСТЬ ДЛЯ ОПРЕДЕЛЕННОЙ ЦЕЛИ. Увидеть
* Стандартная общественная лицензия GNU для получения более подробной информации.
*
* Вы должны были получить копию Стандартной общественной лицензии GNU
* вместе с этой программой; если нет, напишите в Бесплатное ПО
* Foundation, Include., 59 Temple Place, Suite 330, Boston, MA 02111-1307, США
*/
#включать
#include "ns3 / core-module.h"
#include "ns3 / network-module.h"
#include "ns3 / internet-module.h"
#include "ns3 / point-to-point-module.h"
#include "ns3 / applications-module.h"
используя пространство имен ns3;
NS_LOG_COMPONENT_DEFINE («Пятый пример сценария»);
Это все было покрыто, поэтому мы не будем это повторять. Следующие строки источника - это
иллюстрация сети и комментарий, касающийся проблемы, описанной выше, с Розетка.
// ================================================ ===========================
//
// узел 0 узел 1
// + ---------------- + + ---------------- +
// | нс-3 TCP | | нс-3 TCP |
// + ---------------- + + ---------------- +
// | 10.1.1.1 | | 10.1.1.2 |
// + ---------------- + + ---------------- +
// | точка-точка | | точка-точка |
// + ---------------- + + ---------------- +
// | |
// + --------------------- +
// 5 Мбит / с, 2 мс
//
//
// Мы хотим посмотреть на изменения в окне перегрузки TCP ns-3. Нам нужно
// для запуска потока и подключения атрибута CongestionWindow к сокету
// отправителя. Обычно можно использовать приложение включения-выключения для создания
// поток, но здесь есть несколько проблем. Во-первых, розетка включения-выключения
// приложение не создается до времени запуска приложения, поэтому мы не будем
// возможность подключить сокет (сейчас) во время настройки. Во-вторых, даже если мы
// можем организовать вызов после времени запуска, сокет не является публичным, поэтому мы
// не смог добраться до этого.
//
// Итак, мы можем приготовить простую версию двухпозиционного приложения, которое делает то, что
// мы хотим. С другой стороны, нам не нужна вся сложность включения-выключения.
// применение. С другой стороны, у нас нет помощника, поэтому мы должны получить
// немного подробнее, но это тривиально.
//
// Итак, сначала мы создаем сокет и выполняем трассировку подключения к нему; затем мы проходим
// этот сокет в конструктор нашего простого приложения, которое мы затем
// устанавливаем в исходный узел.
// ================================================ ===========================
//
Это также должно быть самоочевидным.
Следующая часть - это объявление Мое приложение Процесс подачи заявки что мы собрали, чтобы позволить
Розетка быть созданным во время настройки.
класс MyApp: общедоступное приложение
{
общественности:
Мое приложение ();
виртуальный ~ MyApp ();
void Setup (Ptr сокет, адрес, адрес, uint32_t packetSize,
uint32_t nPackets, DataRate dataRate);
частный:
виртуальная недействительность StartApplication (недействительна);
виртуальная недействительность StopApplication (недействительна);
недействительным ScheduleTx (недействительным);
void SendPacket (недействителен);
Ptr m_socket;
Адрес m_peer;
uint32_t m_packetSize;
uint32_t m_nПакеты;
Скорость передачи данных m_dataRate;
Идентификатор события m_sendEvent;
логический m_running;
uint32_t m_packetsSent;
};
Вы можете видеть, что этот класс наследуется от нс-3 Процесс подачи заявки класс. Взгляни на
SRC / сеть / модель / application.h если вас интересует то, что передается по наследству. В Мое приложение
класс обязан переопределить Запустить приложение и Остановить приложение методы. Эти
методы автоматически вызываются, когда Мое приложение требуется для запуска и остановки отправки данных
во время моделирования.
Запуск / остановка Приложения
Стоит потратить немного времени на объяснение того, как на самом деле начинаются события в
система. Это еще одно довольно глубокое объяснение, и его можно проигнорировать, если вы не
планируя рискнуть спуститься в самое сердце системы. Однако это полезно в том смысле, что
обсуждение касается того, как некоторые очень важные части нс-3 работа и выставляет некоторые
важные идиомы. Если вы планируете внедрять новые модели, вы, вероятно, захотите
понять этот раздел.
Самый распространенный способ начать накачку событий - запустить Процесс подачи заявки. Это делается как
результат следующих (надеюсь) знакомых строк нс-3 сценарий:
Приложения ApplicationContainer = ...
apps.Start (секунды (1.0));
apps.Stop (секунды (10.0));
Код контейнера приложения (см. SRC / сеть / помощник / приложение-контейнер.h если ты
заинтересовано) проходит через содержащиеся в нем приложения и вызовы,
приложение-> SetStartTime (startTime);
В результате приложения.Начать позвони и
приложение-> SetStopTime (stopTime);
В результате приложения.Стоп вызов.
Конечным результатом этих вызовов является то, что мы хотим, чтобы симулятор автоматически
звонить в наш Приложения чтобы сказать им, когда начать и когда остановиться. В случае
Мое приложение, он наследуется от класса Процесс подачи заявки и отменяет Запустить приложениеи
Остановить приложение. Это функции, которые будут вызываться симулятором в
подходящее время. В случае Мое приложение вы обнаружите, что MyApp :: StartApplication приносит
начальная связующее веществои Связаться в сокете, а затем начинает передачу данных, вызывая
MyApp :: SendPacket. MyApp :: StopApplication прекращает генерацию пакетов, отменяя любые
ожидающие отправки событий затем закрывает сокет.
Одна из приятных вещей в нс-3 в том, что вы можете полностью игнорировать реализацию
подробности о том, как ваш Процесс подачи заявки "автоматически" вызывается симулятором при правильном
время. Но поскольку мы уже углубились в нс-3 уже, давай сделаем это.
Если вы посмотрите на SRC / сеть / модель / application.cc вы обнаружите, что SetStartTime метод
из Процесс подачи заявки просто устанавливает переменную-член m_startTime и SetStopTime метод
просто устанавливает m_stopTime. Оттуда, без каких-либо подсказок, вероятно, и закончится след.
Ключ к повторному поиску следа - это знать, что существует глобальный список всех
узлов в системе. Каждый раз, когда вы создаете узел в симуляции, указатель на этот узел
добавлен в глобальный Список узлов.
Взгляни на SRC / сеть / модель / node-list.cc и найдите NodeList :: Добавить, Публика
вызовы статической реализации в частную реализацию, называемую NodeListPriv :: Добавить. Это
является относительно распространенным идомом в нс-3. Итак, взгляните на NodeListPriv :: Добавить. Там вы
найду,
Simulator :: ScheduleWithContext (индекс, TimeStep (0), & Node :: Initialize, узел);
Это говорит вам о том, что всякий раз, когда узел создается в симуляции, в качестве побочного эффекта вызывается вызов
к этому узлу инициализировать для вас запланирован метод, который происходит в нулевое время. Не надо
пока слишком много не зачитываю в этом имени. Это не значит, что Узел начнет делать
что угодно, это можно интерпретировать как информационный вызов в Узел, сообщающий ему, что
симуляция началась, а не призыв к действию, говорящий Узлу начать что-то делать.
Итак, NodeList :: Добавить косвенно назначает звонок Узел :: Инициализировать в нулевое время, чтобы посоветовать
new Node, что моделирование было запущено. Если вы посмотрите в SRC / сеть / модель / node.h
однако не найдет метод с именем Узел :: Инициализировать, Оказывается, что
инициализировать метод унаследован от класса объект. Все объекты в системе могут быть
уведомляется, когда начинается симуляция, и объекты класса Node являются лишь одним из них
объекты.
Взгляни на SRC / ядро / модель / объект.cc далее и ищите Объект :: Инициализировать. Этот код
не так просто, как вы могли ожидать, так как нс-3 Объекты поддержка
агрегация. Код в Объект :: Инициализировать затем перебирает все объекты,
собраны вместе и называют их Сделать инициализацию метод. Это еще одна идиома
это очень распространено в нс-3, иногда называемый "шаблоном проектирования": общедоступный
невиртуальный метод API, который остается постоянным во всех реализациях и вызывает
частный виртуальный метод реализации, который наследуется и реализуется подклассами.
Имена обычно выглядят примерно так: имя метода для общедоступного API и ИмяДоМетода для
частный API.
Это говорит нам о том, что мы должны искать Узел :: DoInitialize метод в
SRC / сеть / модель / node.cc для метода, который продолжит наш след. Если вы найдете
код, вы найдете метод, который проходит через все устройства в узле, а затем
все приложения в вызывающем узле устройство-> Инициализировать и приложение-> Инициализировать
соответственно.
Возможно, вы уже знаете, что классы Устройство и Процесс подачи заявки оба наследуются от класса объект
и поэтому следующим шагом будет посмотреть, что происходит, когда Приложение :: DoInitialize is
называется. Взгляни на SRC / сеть / модель / application.cc и вы найдете:
аннулировать
Приложение :: DoInitialize (недействительно)
{
m_startEvent = Simulator :: Schedule (m_startTime, & Application :: StartApplication, это);
если (m_stopTime! = TimeStep (0))
{
m_stopEvent = Simulator :: Schedule (m_stopTime, & Application :: StopApplication, это);
}
Объект :: DoInitialize ();
}
Вот мы и подошли к концу тропы. Если ты держишь все прямо, когда ты
реализовать нс-3 Процесс подачи заявки, ваше новое приложение наследуется от класса Процесс подачи заявки. Вы
преодолеть Запустить приложение и Остановить приложение методы и предоставить механизмы для
запуск и остановка потока данных из вашего нового Процесс подачи заявки. Когда узел
созданный в моделировании, он добавляется в глобальный Список узлов. Акт добавления узла в
этой Список узлов заставляет событие симулятора быть запланировано на нулевое время, которое вызывает
Узел :: Инициализировать метод только что добавленного узла, который будет вызываться при запуске моделирования.
Поскольку узел наследуется от объект, это вызывает Объект :: Инициализировать метод на узле
который, в свою очередь, вызывает Сделать инициализацию методы на всех Объекты в совокупности с
Узел (подумайте о моделях мобильности). Поскольку узел объект переопределено Сделать инициализацию, Что
метод вызывается при запуске моделирования. В Узел :: DoInitialize метод вызывает
инициализировать методы всех Приложения на узле. С Приложения являются также
Объекты, это вызывает Приложение :: DoInitialize быть вызванным. Когда
Приложение :: DoInitialize называется, он планирует события для Запустить приложение и
Остановить приложение призывает Процесс подачи заявки. Эти вызовы предназначены для запуска и остановки
поток данных из Процесс подачи заявки
Это было еще одно довольно долгое путешествие, но его нужно совершить только один раз, и теперь вы
понять еще один очень глубокий кусок нс-3.
Команда Мое приложение Процесс подачи заявки
Команда Мое приложение Процесс подачи заявки Конечно, нужен конструктор и деструктор:
MyApp :: MyApp ()
: m_socket (0),
м_пир (),
м_пакетсизе (0),
m_nПакеты (0),
м_данныеРате (0),
m_sendEvent(),
m_running (ложь),
m_packetsSent (0)
{
}
MyApp :: ~ MyApp ()
{
м_сокет = 0;
}
Существование следующего фрагмента кода - вот вся причина, по которой мы написали это Процесс подачи заявки in
первое место.
аннулировать
MyApp :: Настройка (Ptr сокет, адрес, адрес, uint32_t packetSize,
uint32_t nPackets, DataRate dataRate)
{
m_socket = сокет;
m_peer = адрес;
m_packetSize = размер пакета;
m_nPackets = nПакетов;
m_dataRate = скорость передачи данных;
}
Этот код не требует пояснений. Мы просто инициализируем переменные-члены.
Важным с точки зрения отслеживания является Ptr гнездо который мы
необходимо предоставить приложению во время настройки. Напомним, что мы идем
для создания Розетка как TCPSocket (который реализуется TcpNewReno) и зацепите его
Источник трассировки "CongestionWindow" перед его передачей в Установка метод.
аннулировать
MyApp :: StartApplication (недействительно)
{
m_running = истина;
m_packetsSent = 0;
m_socket-> Привязать ();
m_socket-> Подключить (m_peer);
ОтправитьПакет();
}
Приведенный выше код является переопределенной реализацией Приложение :: StartApplication это будет
автоматически вызывается симулятором для запуска нашего Процесс подачи заявки работает на подходящем
время. Вы можете видеть, что это Розетка связующее вещество операция. Если вы знакомы с
Berkeley Sockets это не должно вызывать удивления. Выполняет необходимые работы на локальном
сторона соединения, как и следовало ожидать. Следующее Связаться буду делать то, что есть
требуется для установления соединения с TCP на Адрес m_peer. Теперь должно быть ясно
почему нам нужно откладывать большую часть этого на время моделирования, поскольку Связаться понадобится
полностью функционирующая сеть. После Связаться, Процесс подачи заявки затем начинается
создание событий моделирования путем вызова Отправить пакет.
Следующий фрагмент кода объясняет Процесс подачи заявки как перестать создавать симуляционные события.
аннулировать
MyApp :: StopApplication (недействительно)
{
m_running = ложь;
если (m_sendEvent.IsRunning ())
{
Симулятор :: Отмена (m_sendEvent);
}
если (m_socket)
{
m_socket-> Закрыть ();
}
}
Каждый раз, когда запланировано событие моделирования, События создано. Если События находится на рассмотрении
исполнение или исполнение, его метод Это работает вернется правда. В этом коде, если
Это работает() возвращается правда, мы Отмена событие, которое удаляет его из события симулятора
очередь. Делая это, мы разрываем цепочку событий, которые Процесс подачи заявки использует, чтобы сохранить
отправка своего Пакеты и Процесс подачи заявки уходит тихо. После того, как мы успокоим Процесс подачи заявки we
Закрыто сокет, который разрывает TCP-соединение.
Сокет фактически удаляется в деструкторе, когда m_socket = 0 выполняется. Этот
удаляет последнюю ссылку на базовый Ptr что вызывает деструктор
этот объект должен быть вызван.
Напомним, что Запустить приложение под названием Отправить пакет запустить цепочку событий, описывающих
Процесс подачи заявки поведение.
аннулировать
MyApp :: SendPacket (недействительно)
{
Ptr package = Создать (m_packetSize);
m_socket-> Отправить (пакет);
если (++ m_packetsSent <m_nPackets)
{
РасписаниеTx ();
}
}
Здесь вы видите, что Отправить пакет делает именно это. Это создает пакет а затем делает Отправьте
что, если вы знаете Berkeley Sockets, вероятно, именно то, что вы ожидали увидеть.
Это ответственность Процесс подачи заявки продолжать планировать цепочку событий, чтобы
вызов следующей линии РасписаниеTx чтобы запланировать другое событие передачи (a Отправить пакет) до
Процесс подачи заявки решает, что отправлено достаточно.
аннулировать
MyApp :: ScheduleTx (недействительно)
{
если (m_running)
{
Время tNext (секунды (m_packetSize * 8 / static_cast (m_dataRate.GetBitRate ())));
m_sendEvent = Simulator :: Schedule (tNext, & MyApp :: SendPacket, это);
}
}
Здесь вы видите, что РасписаниеTx делает именно это. Если Процесс подачи заявки работает (если
Остановить приложение не был вызван) он запланирует новое событие, которое вызывает Отправить пакет
снова. Читатель предупреждений обнаружит что-то, что также сбивает с толку новых пользователей. Скорость передачи данных
из Процесс подачи заявки это просто так. Это не имеет ничего общего со скоростью передачи данных базового
Канал. Это скорость, с которой Процесс подачи заявки производит биты. Не принимает во внимание
учитывать любые накладные расходы для различных протоколов или каналов, которые он использует для транспортировки
данные. Если вы установите скорость передачи данных Процесс подачи заявки с той же скоростью передачи данных, что и ваш базовый
Канал вы в конечном итоге получите переполнение буфера.
Прослеживать Мойки
Весь смысл этого упражнения - получить обратные вызовы трассировки от TCP, указывающие на
обновлено окно перегрузки. Следующий фрагмент кода реализует соответствующий
раковина следа:
статическая пустота
CwndChange (uint32_t oldCwnd, uint32_t newCwnd)
{
NS_LOG_UNCOND (Simulator :: Now () .GetSeconds () << "\ t" << newCwnd);
}
Теперь это должно быть вам хорошо знакомо, поэтому мы не будем останавливаться на деталях. Эта функция
просто регистрирует текущее время моделирования и новое значение окна перегрузки каждые
время его изменили. Вы, вероятно, можете представить, что можете загрузить полученный результат
в графическую программу (gnuplot или Excel) и сразу увидите красивый график
поведение окна перегрузки с течением времени.
Мы добавили новый приемник трассировки, чтобы показать, где отбрасываются пакеты. Мы собираемся добавить ошибку
model к этому коду, поэтому мы хотели продемонстрировать, как это работает.
статическая пустота
RxDrop (Ptr п)
{
NS_LOG_UNCOND ("RxDrop at" << Simulator :: Now () .GetSeconds ());
}
Этот приемник трассировки будет подключен к источнику трассировки «PhyRxDrop» двухточечного соединения.
NetDevice. Этот источник трассировки срабатывает, когда пакет отбрасывается физическим уровнем
NetDevice. Если вы сделаете небольшой объезд к источнику
(SRC / точка-точка / модель / точка-точка-net-device.cc) вы увидите, что этот след
источник относится к PointToPointNetDevice :: m_phyRxDropTrace. Если вы затем заглянете
SRC / точка-точка / модель / точка-точка-сеть-устройство.h для этой переменной-члена вы будете
обнаружил, что он объявлен как TracedCallback Пакет> >. Это должно вам сказать
что целью обратного вызова должна быть функция, которая возвращает void и принимает единственный
параметр, который является Ptr Пакет> (при условии, что мы используем Подключить без контекста) -- просто
что у нас есть выше.
Главная Программа
Следующий код должен быть вам хорошо знаком:
Int
main (int argc, char * argv [])
{
Узлы NodeContainer;
node.Create (2);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5 Мбит / с"));
pointToPoint.SetChannelAttribute («Задержка», StringValue («2 мс»));
Устройства NetDeviceContainer;
devices = pointToPoint.Install (узлы);
Это создает два узла с двухточечным каналом между ними, как показано на рисунке.
иллюстрация в начале файла.
Следующие несколько строк кода показывают что-то новое. Если мы отслеживаем соединение, которое ведет себя
в идеале мы получим монотонно увеличивающееся окно перегрузки. Чтобы увидеть любой
интересное поведение, мы действительно хотим ввести ошибки связи, которые будут отбрасывать пакеты,
вызывают дублирование ACK и запускают более интересное поведение окна перегрузки.
нс-3 приводит Модель ошибки объекты, которые можно прикрепить к Каналы. Мы используем
Ратееррормодель что позволяет нам вносить ошибки в Канал в данный момент скорость.
Ptr em = CreateObject ();
em-> SetAttribute ("ErrorRate", DoubleValue (0.00001));
devices.Get (1) -> SetAttribute ("ReceiveErrorModel", PointerValue (em));
Приведенный выше код создает экземпляр Ратееррормодель Object, и мы устанавливаем "ErrorRate" Атрибут
до желаемого значения. Затем мы устанавливаем результирующий экземпляр Ратееррормодель как ошибка
модель, используемая для двухточечной связи NetDevice. Это даст нам несколько повторных передач и
сделаем наш сюжет немного интереснее.
стек InternetStackHelper;
stack.Install (узлы);
IPv4AddressHelper адрес;
address.SetBase ("10.1.1.0", "255.255.255.252");
Интерфейсы Ipv4InterfaceContainer = address.Assign (устройства);
Приведенный выше код должен быть вам знаком. Он устанавливает интернет-стеки на два наших узла и
создает интерфейсы и назначает IP-адреса устройствам точка-точка.
Поскольку мы используем TCP, нам нужно что-то на узле назначения для получения TCP.
подключения и данные. В ПакетСинк Процесс подачи заявки обычно используется в нс-3 для этого
цель.
uint16_tinkPort = 8080;
АдресinkAddress (InetSocketAddress (interfaces.GetAddress (1) ,inkPort));
PacketSinkHelper packetSinkHelper ("ns3 :: TcpSocketFactory",
InetSocketAddress (Ipv4Address :: GetAny () ,inkPort));
ApplicationContainer SinkApps = packetSinkHelper.Install (nodes.Get (1));
раковинаApps.Start (секунды (0.));
раковинаApps.Stop (Секунды (20.));
Все это должно быть вам знакомо, за исключением,
PacketSinkHelper packetSinkHelper ("ns3 :: TcpSocketFactory",
InetSocketAddress (Ipv4Address :: GetAny () ,inkPort));
Этот код создает экземпляр ПакетSinkHelper и сообщает ему о создании сокетов с использованием класса
ns3 :: TcpSocketFactory. Этот класс реализует шаблон проектирования под названием «фабрика объектов».
который является обычно используемым механизмом для указания класса, используемого для создания объектов в
абстрактный путь. Здесь вместо того, чтобы создавать сами объекты, вы предоставляете
ПакетSinkHelper строка, определяющая Идентификатор типа строка, используемая для создания объекта, который
затем можно использовать, в свою очередь, для создания экземпляров объектов, созданных фабрикой.
Остающийся параметр сообщает Процесс подачи заявки какой адрес и порт он должен связующее вещество к.
Следующие две строки кода создадут сокет и подключат источник трассировки.
Ptr ns3TcpSocket = Socket :: CreateSocket (nodes.Get (0),
TcpSocketFactory :: GetTypeId ());
ns3TcpSocket-> TraceConnectWithoutContext ("CongestionWindow",
MakeCallback (& CwndChange));
Первый оператор вызывает статическую функцию-член Socket :: CreateSocket и предоставляет
Узел и явный Идентификатор типа для фабрики объектов, используемой для создания сокета. Это
вызов чуть более низкого уровня, чем ПакетSinkHelper вызов выше, и использует явный C ++
тип вместо того, на который ссылается строка. В остальном это концептуально то же самое
вещь.
Как только появится строка TCPSocket создается и прикрепляется к узлу, мы можем использовать
Трассеконнектвисаутконтекст для подключения источника трассировки CongestionWindow к нашему приемнику трассировки.
Напомним, что мы закодировали Процесс подачи заявки чтобы мы могли принять это Розетка мы только что сделали (во время
время конфигурации) и использовать его во время моделирования. Теперь нам нужно создать экземпляр этого
Процесс подачи заявки. Мы не составили труда создать помощника для управления Процесс подачи заявки so
нам придется создать и установить его «вручную». На самом деле это довольно просто:
Ptr app = CreateObject ();
приложение-> Настройка (ns3TcpSocket ,inkAddress, 1040, 1000, DataRate («1 Мбит / с»));
nodes.Get (0) -> AddApplication (приложение);
приложение-> Старт (секунды (1.));
app-> Stop (Секунды (20.));
Первая строка создает объект типа Мое приложение -- наш Процесс подачи заявки. Вторая строка сообщает
Процесс подачи заявки почему Розетка использовать, к какому адресу подключаться, сколько данных отправлять на
каждое событие отправки, сколько событий отправки нужно сгенерировать и скорость, с которой производятся данные
от тех событий.
Затем мы вручную добавляем Мое приложение Процесс подачи заявки к исходному узлу и явно вызвать
Начните и Stop методы на Процесс подачи заявки сказать ему, когда начать и прекратить делать свое
вещь.
Нам нужно установить соединение от приемника точка-точка. NetDevice событие сброса
нашим RxDrop обратный звонок сейчас.
devices.Get (1) -> TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (& RxDrop));
Теперь должно быть очевидно, что мы получаем ссылку на получение Узел NetDevice
из своего контейнера и подключения источника трассировки, определенного атрибутом «PhyRxDrop» на
это устройство в приемник трассировки RxDrop.
Наконец, мы говорим симулятору игнорировать любые Приложения и просто прекратите обработку
события через 20 секунд после начала моделирования.
Симулятор :: Стоп (Секунд(20));
Симулятор :: Беги ();
Симулятор :: Уничтожить ();
0 вернуться;
}
Напомним, что как только Симулятор :: Беги вызывается, время настройки заканчивается, и моделирование
время начинается. Всю работу мы организовали, создав Процесс подачи заявки и обучение этому
то, как подключаться и отправлять данные, действительно происходит во время этого вызова функции.
Как только Симулятор :: Беги возвращается, моделирование завершено, и мы входим в разборку
фаза. В таком случае, Симулятор :: Уничтожить позаботится о кровавых деталях, и мы просто вернемся
код успеха после его завершения.
Бег Friday.cc
Поскольку мы предоставили файл Friday.cc для вас, если вы создали свой дистрибутив (в
режим отладки, поскольку он использует НС_ЛОГ - напомним, что оптимизированные сборки оптимизируют НС_ЛОГ) Это
будет ждать, пока вы побежите.
$ ./waf - запустить пятый
Waf: вход в каталог `/ home / craigdo / repos / ns-3-allinone-dev / ns-3-dev / build '
Waf: выход из каталога `/ home / craigdo / repos / ns-3-allinone-dev / ns-3-dev / build '
'build' успешно завершена (0.684 с)
1 536
1.0093 1072
1.01528 1608
1.02167 2144
...
1.11319 8040
1.12151 8576
1.12983 9112
RxDrop на уровне 1.13696
...
Вы, вероятно, сразу заметите обратную сторону использования любых отпечатков в ваших следах.
Мы печатаем эти посторонние сообщения Waf по всей нашей интересной информации.
с этими сообщениями RxDrop. Мы скоро это исправим, но я уверен, что тебе не терпится увидеть
результаты всей этой работы. Давайте перенаправим этот вывод в файл с именем cwnd.dat:
$ ./waf - запустить пятый> cwnd.dat 2> & 1
Теперь отредактируйте "cwnd.dat" в вашем любимом редакторе, удалите статус сборки waf и отпустите
строк, оставив только отслеженные данные (вы также можете закомментировать
TraceConnectWithoutContext ("PhyRxDrop", Обратный звонок (& RxDrop)); в сценарии, чтобы избавиться
капель печатается так же легко.
Теперь вы можете запустить gnuplot (если он у вас установлен) и сказать ему, чтобы он сгенерировал довольно
фотографий:
$ гнуплот
gnuplot> установить терминал png размером 640,480 XNUMX
gnuplot> установить вывод "cwnd.png"
gnuplot> построить "cwnd.dat", используя заголовок 1: 2 "Окно перегрузки" с точками строк
gnuplot> выход
Теперь у вас должен быть график окна перегрузки в зависимости от времени нахождения в файле.
"cwnd.png" loading = "ленивый", который выглядит так:
[Image]
. Средний уровень Помощники
В предыдущем разделе мы показали, как подключить источник трассировки и, надеюсь, получить
интересная информация из симуляции. Возможно, вы помните, что мы звонили
запись в стандартный вывод с помощью std :: cout «тупым орудием» гораздо раньше в этом
глава. Мы также писали о том, как возникла проблема с анализом вывода журнала по порядку.
изолировать интересную информацию. Возможно, вам пришло в голову, что мы просто потратили много
времени на реализацию примера, демонстрирующего все проблемы, которые мы пытаемся исправить с помощью
нс-3 система отслеживания! Вы были бы правы. Но потерпите нас. Мы еще не закончили.
Одна из самых важных вещей, которую мы хотим сделать, - это иметь возможность легко
контролировать количество выходных данных моделирования; и мы также хотим сохранить эти
data в файл, чтобы мы могли вернуться к нему позже. Мы можем использовать помощники трассировки среднего уровня
предоставляется в нс-3 чтобы сделать именно это и завершить картину.
Мы предоставляем сценарий, который записывает события изменения и удаления cwnd, разработанные в примере.
Friday.cc на диск отдельными файлами. Изменения cwnd сохраняются в виде ASCII, разделенного табуляцией.
файл, а события сброса сохраняются в файле PCAP. Чтобы это произошло, внесены следующие изменения:
довольно маленький.
Прохождение: шестой.cc
Давайте посмотрим на изменения, необходимые для перехода с Friday.cc в шестой.cc, открыто
примеры / учебник / sixth.cc в вашем любимом редакторе. Вы можете увидеть первое изменение по
ищет CwndChange. Вы обнаружите, что мы изменили подписи для трассировки
приемников и добавили по одной строке к каждому приемнику, который записывает отслеживаемую информацию в
поток, представляющий файл.
статическая пустота
CwndChange (Ptr поток, uint32_t oldCwnd, uint32_t newCwnd)
{
NS_LOG_UNCOND (Simulator :: Now () .GetSeconds () << "\ t" << newCwnd);
* stream-> GetStream () << Simulator :: Now () .GetSeconds () << "\ t" << oldCwnd << "\ t" << newCwnd << std :: endl;
}
статическая пустота
RxDrop (Ptr файл, Ptr п)
{
NS_LOG_UNCOND ("RxDrop at" << Simulator :: Now () .GetSeconds ());
файл-> Запись (Simulator :: Now (), p);
}
Мы добавили параметр "поток" в CwndChange след мойка. Это объект, который
содержит (безопасно поддерживает) выходной поток C ++. Оказывается, это очень простой
объект, но тот, который управляет проблемами времени жизни для потока и решает проблему, которая даже
опытные пользователи C ++ сталкиваются с. Оказывается, конструктор копирования для std :: ostream
отмечен как частный. Это означает, что std :: ostreams не подчиняются семантике значений и не могут
использоваться в любом механизме, который требует копирования потока. Это включает нс-3
система обратного вызова, которая, как вы помните, требует объектов, подчиняющихся семантике значений.
Обратите внимание, что мы добавили следующую строку в CwndChange след раковина
реализация:
* stream-> GetStream () << Simulator :: Now () .GetSeconds () << "\ t" << oldCwnd << "\ t" << newCwnd << std :: endl;
Это был бы очень знакомый код, если бы вы заменили * поток-> GetStream () std :: cout, так как
в:
std :: cout << Simulator :: Now () .GetSeconds () << "\ t" << oldCwnd << "\ t" << newCwnd << std :: endl;
Это показывает, что Ptr действительно просто таскает с собой
std :: ofstream для вас, и вы можете использовать его здесь, как любой другой выходной поток.
Похожая ситуация бывает в RxDrop за исключением того, что передаваемый объект (a
Ptr) представляет файл PCAP. В приемнике трассировки есть однострочник, чтобы
запишите метку времени и содержимое отбрасываемого пакета в файл PCAP:
файл-> Запись (Simulator :: Now (), p);
Конечно, если у нас есть объекты, представляющие два файла, нам нужно где-то их создать.
а также заставляют их передаваться в приемники трассировки. Если вы посмотрите в main Функция,
вы найдете новый код для этого:
AsciiTraceHelper asciiTraceHelper;
Ptr stream = asciiTraceHelper.CreateFileStream ("шестой.cwnd");
ns3TcpSocket-> TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (& CwndChange, stream));
...
ПкапХелпер
Ptr file = pcapHelper.CreateFile ("шестой.pcap", std :: ios :: out, PcapHelper :: DLT_PPP);
devices.Get (1) -> TraceConnectWithoutContext ("PhyRxDrop", MakeBoundCallback (& RxDrop, файл));
В первом разделе приведенного выше фрагмента кода мы создаем файл трассировки ASCII,
создание объекта, отвечающего за управление им, и использование варианта обратного вызова
функция создания, чтобы организовать передачу объекта в приемник. Наша трассировка ASCII
Помощники предоставляют богатый набор функций, упрощающих использование текстовых файлов (ASCII). Мы
Я просто собираюсь проиллюстрировать здесь использование функции создания файлового потока.
Команда Создать поток файлов функция в основном собирается создать экземпляр std :: ofstream объект и
создать новый файл (или обрезать существующий). Этот std :: ofstream упакован в
нс-3 объект для управления жизненным циклом и решения проблем с конструктором копирования.
Затем мы берем это нс-3 объект, представляющий файл, и передать его в MakeBoundCallback ().
Эта функция создает обратный вызов точно так же, как MakeCallback (), но он "привязывает" новое значение к
обратный вызов. Это значение добавляется в качестве первого аргумента обратного вызова перед тем, как оно будет
называется.
По существу, MakeBoundCallback (& CwndChange, поток) заставляет источник трассировки добавить
дополнительный параметр "поток" в начале списка формальных параметров перед вызовом
обратный вызов. Это изменяет требуемую подпись CwndChange раковина, чтобы соответствовать одному
показанный выше, который включает "дополнительный" параметр Ptr поток.
Во втором разделе кода в приведенном выше фрагменте мы создаем экземпляр PcapHelper сделать
то же самое для нашего файла трассировки PCAP, которое мы сделали с AsciiTraceHelper, Линия
код,
Ptr file = pcapHelper.CreateFile ("шестой.pcap",
«w», PcapHelper :: DLT_PPP);
создает файл PCAP с именем "sixth.pcap" с файловым режимом "w". Это означает, что новый файл
обрезается (содержимое удаляется), если найден существующий файл с таким именем. Финал
Параметр - это "тип канала передачи данных" нового файла PCAP. Они такие же, как PCAP
типы ссылок на данные библиотеки, определенные в бпф.ч если вы знакомы с PCAP. В таком случае,
ДЛТ_ППП указывает, что файл PCAP будет содержать пакеты с префиксом point to
заголовки точек. Это правда, поскольку пакеты приходят от нашего устройства точка-точка.
Водитель. Другими распространенными типами каналов передачи данных являются DLT_EN10MB (10 МБ Ethernet), подходящие для CSMA.
устройства и DLT_IEEE802_11 (IEEE 802.11), подходящие для устройств Wi-Fi. Они определены
in SRC / сеть / помощник / трассировка-помощник.h если вы хотите увидеть список. В
записи в списке совпадают с записями в бпф.ч но мы дублируем их, чтобы избежать источника PCAP
зависимость.
A нс-3 объект, представляющий файл PCAP, возвращается из Создать файл и используется в связке
обратный вызов точно так же, как и в случае ASCII.
Важный обходной путь: важно отметить, что хотя оба эти объекта
заявлено очень похожим образом,
Ptr файл ...
Ptr ручей ...
Базовые объекты совершенно разные. Например, Ptr - это
умный указатель на нс-3 Объект, который представляет собой довольно тяжелую вещь, которая поддерживает
Атрибуты и интегрирован в систему Config. В Ptr, На
с другой стороны, это умный указатель на объект с подсчетом ссылок, который является очень легким
вещь. Не забудьте посмотреть на объект, на который вы ссылаетесь, прежде чем делать какие-либо предположения.
о «силах», которые может иметь этот объект.
Например, взгляните на SRC / сеть / utils / pcap-файл-обертка.h в распределении и
уведомление,
класс PcapFileWrapper: публичный объект
этот класс PcapFileWrapper есть нс-3 Объект в силу его наследственности. Тогда посмотри на
SRC / сеть / модель / выходной поток-обертка.h и обратите внимание,
класс OutputStreamWrapper: общедоступный
SimpleRefCount
что этот объект не нс-3 Объект вообще, это "просто" объект C ++, который случается с
поддерживать навязчивый подсчет ссылок.
Дело в том, что только потому, что вы читаете Ptr это не обязательно означает
который удалось есть нс-3 Объект, на который можно повесить нс-3 Атрибуты, например.
А теперь вернемся к примеру. Если вы соберете и запустите этот пример,
$ ./waf - запустить шестой
вы увидите те же сообщения, что и при запуске "пятого", но два новых файла будут
появятся в каталоге верхнего уровня вашего нс-3 распределение.
шестой.cwnd шестой.pcap
Поскольку "sixth.cwnd" является текстовым файлом ASCII, вы можете просмотреть его с помощью кошка или ваш любимый файл
Зритель.
1 0 536
1.0093 536 1072
1.01528 1072 1608
1.02167 1608 2144
...
9.69256 5149 5204
9.89311 5204 5259
У вас есть файл, разделенный табуляцией, с меткой времени, старым окном перегрузки и новым
окно перегрузки, подходящее для прямого импорта в вашу программу построения графиков. Нет
посторонние отпечатки в файле не требуют синтаксического анализа и редактирования.
Поскольку "sixth.pcap" является файлом PCAP, вы можете просмотреть его с помощью ТСРйитр.
чтение из файла sixth.pcap, ссылочный PPP (PPP)
1.136956 IP 10.1.1.1.49153> 10.1.1.2.8080: флаги [.], Seq 17177: 17681, ack 1, win 32768, параметры [TS val 1133 ecr 1127, eol], длина 504
1.403196 IP 10.1.1.1.49153> 10.1.1.2.8080: флаги [.], Seq 33280: 33784, ack 1, win 32768, параметры [TS val 1399 ecr 1394, eol], длина 504
...
7.426220 IP 10.1.1.1.49153> 10.1.1.2.8080: флаги [.], Seq 785704: 786240, ack 1, win 32768, параметры [TS val 7423 ecr 7421, eol], длина 536
9.630693 IP 10.1.1.1.49153> 10.1.1.2.8080: флаги [.], Seq 882688: 883224, ack 1, win 32768, параметры [TS val 9620 ecr 9618, eol], длина 536
У вас есть файл PCAP с пакетами, которые были отброшены при моделировании. Нет
другие пакеты, присутствующие в файле, и в нем нет ничего, что могло бы оживить
сложно.
Это был долгий путь, но сейчас мы находимся в точке, где мы можем оценить нс-3
система отслеживания. Мы вытащили важные события из середины реализации TCP.
и драйвер устройства. Мы сохранили эти события непосредственно в файлах, которые можно использовать с общеизвестными
инструменты. Мы сделали это без изменения какого-либо задействованного основного кода, и мы сделали это в
всего 18 строк кода:
статическая пустота
CwndChange (Ptr поток, uint32_t oldCwnd, uint32_t newCwnd)
{
NS_LOG_UNCOND (Simulator :: Now () .GetSeconds () << "\ t" << newCwnd);
* stream-> GetStream () << Simulator :: Now () .GetSeconds () << "\ t" << oldCwnd << "\ t" << newCwnd << std :: endl;
}
...
AsciiTraceHelper asciiTraceHelper;
Ptr stream = asciiTraceHelper.CreateFileStream ("шестой.cwnd");
ns3TcpSocket-> TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (& CwndChange, stream));
...
статическая пустота
RxDrop (Ptr файл, Ptr п)
{
NS_LOG_UNCOND ("RxDrop at" << Simulator :: Now () .GetSeconds ());
файл-> Запись (Simulator :: Now (), p);
}
...
ПкапХелпер
Ptr file = pcapHelper.CreateFile («шестой.pcap», «w», PcapHelper :: DLT_PPP);
devices.Get (1) -> TraceConnectWithoutContext ("PhyRxDrop", MakeBoundCallback (& RxDrop, файл));
Прослеживать Помощники
Команда нс-3 помощники по трассировке предоставляют богатую среду для настройки и выбора различных
отслеживать события и записывать их в файлы. В предыдущих разделах в первую очередь
BuildingTopologies, мы видели несколько разновидностей вспомогательных методов трассировки, разработанных
для использования внутри других помощников (устройства).
Возможно, вы помните, что видели некоторые из этих вариаций:
pointToPoint.EnablePcapAll («второй»);
pointToPoint.EnablePcap («второй», p2pNodes.Get (0) -> GetId (), 0);
csma.EnablePcap ("третий", csmaDevices.Get (0), истина);
pointToPoint.EnableAsciiAll (ascii.CreateFileStream ("myfirst.tr"));
Что может быть неочевидным, так это то, что существует последовательная модель для всех
методы, связанные с трассировкой, найденные в системе. Сейчас мы уделим немного времени и взглянем
на «общую картину».
В настоящее время существует два основных варианта использования помощников по трассировке в нс-3: помощники по устройству
и помощники протокола. Помощники по устройствам решают проблему определения следов
должен быть включен через пару (узел, устройство). Например, вы можете указать
что трассировка PCAP должна быть включена на определенном устройстве на определенном узле. Этот
следует из нс-3 концептуальная модель устройства, а также концептуальные модели
различные помощники устройства. Естественно, следуя этому, созданные файлы следуют
- - соглашение об именовании.
Помощники протокола рассматривают проблему указания, какие трассировки должны быть включены через
пара протокола и интерфейса. Это следует из нс-3 концептуальный стек протоколов
модель, а также концептуальные модели помощников интернет-стека. Естественно, след
файлы должны следовать - - соглашение об именовании.
Таким образом, помощники трассировки естественным образом попадают в двухмерную таксономию. Есть
тонкости, которые мешают всем четырем классам вести себя одинаково, но мы стремимся к тому, чтобы
сделать так, чтобы все они работали как можно схоже; и по возможности есть аналоги для
все методы во всех классах.
┌────────────────┬──────┬───────
│ │ PCAP │ ASCII │
└────────────────┴──────┴───────
│Помощник по устройству │ │ │
├────────────────┼──────┼───────
│Программный помощник │ │ │
└────────────────┴──────┴───────
Мы используем подход, называемый Mixin чтобы добавить функцию трассировки в наши вспомогательные классы. А
Mixin - это класс, который предоставляет функциональные возможности, когда он наследуется подклассом.
Наследование от миксина не считается формой специализации, но на самом деле является способом
собрать функционал.
Давайте кратко рассмотрим все четыре случая и их соответствующие Примеси.
Устройство Помощники
ПКАП
Цель этих помощников - упростить добавление единообразного средства трассировки PCAP к
нс-3 устройство. Мы хотим, чтобы все разновидности трассировки PCAP работали одинаково во всех
все устройства, поэтому методы этих помощников наследуются помощниками устройств. Посмотри
at SRC / сеть / помощник / трассировка-помощник.h если вы хотите следить за обсуждением, глядя на
реальный код.
Класс Пкахелперфордевице - это Mixin обеспечивает функциональность высокого уровня для использования
Отслеживание PCAP в нс-3 устройство. Каждое устройство должно реализовывать один виртуальный метод
унаследован от этого класса.
virtual void EnablePcapInternal (префикс std :: string, Ptr nd, bool promiscuous, bool explicitFilename) = 0;
Сигнатура этого метода отражает аппаратно-ориентированный взгляд на ситуацию на данном этапе.
уровень. Все общедоступные методы, унаследованные от класса Пкапусерхелперфордевице сократить до
вызов этого единственного метода реализации, зависящего от устройства. Например, самый низкий уровень
Метод PCAP,
void EnablePcap (префикс std :: string, Ptr nd, bool promiscuous = false, bool explicitFilename = false);
вызовет реализацию устройства EnablePcapInternal напрямую. Все остальные общедоступные PCAP
методы трассировки основаны на этой реализации, чтобы обеспечить дополнительный уровень пользователя
функциональность. Для пользователя это означает, что все помощники устройств в системе будут
иметь все доступные методы трассировки PCAP; и все эти методы будут работать в одном
путь через устройства, если устройство реализует EnablePcapInternal правильно.
методы
void EnablePcap (префикс std :: string, Ptr nd, bool promiscuous = false, bool explicitFilename = false);
void EnablePcap (std :: string prefix, std :: string ndName, bool promiscuous = false, bool explicitFilename = false);
void EnablePcap (std :: string prefix, NetDeviceContainer d, bool promiscuous = false);
void EnablePcap (std :: string prefix, NodeContainer n, bool promiscuous = false);
void EnablePcap (std :: string prefix, uint32_t nodeid, uint32_t deviceid, bool promiscuous = false);
void EnablePcapAll (префикс std :: string, bool promiscuous = false);
В каждом из методов, показанных выше, есть параметр по умолчанию, называемый разнородный который
по умолчанию ложный. Этот параметр указывает, что трассировку не следует собирать в
беспорядочный режим. Если вы хотите, чтобы ваши трассировки включали весь трафик, видимый устройством
(и если устройство поддерживает неразборчивый режим) просто добавьте истинный параметр к любому из
звонки выше. Например,
Ptr nd;
...
helper.EnablePcap («префикс», nd, истина);
включит неразборчивый режим захвата на NetDevice указано nd.
Первые два метода также включают параметр по умолчанию, называемый явное имя файла что будет
обсуждается ниже.
Предлагаем вам ознакомиться с документацией по API для класса Пкахелперфордевице найти
детали этих методов; но подведем итог ...
· Вы можете включить отслеживание PCAP для конкретной пары узел / сеть-устройство, предоставив
Ptr к ВключитьPcap метод. Ptr неявно, поскольку сетевое устройство
должен принадлежать ровно одному узлу. Например,
Ptr nd;
...
helper.EnablePcap («префикс», nd);
· Вы можете включить отслеживание PCAP для конкретной пары узел / сеть-устройство, предоставив
станд :: строка представление служебной строки имени объекта для ВключитьPcap метод.
Ptr ищется из строки имени. Опять же, неявно, поскольку
названное сетевое устройство должно принадлежать ровно одному узлу. Например,
Names :: Add ("сервер" ...);
Имена :: Добавить ("server / eth0" ...);
...
helper.EnablePcap («префикс», «сервер / ath0»);
· Вы можете включить отслеживание PCAP для набора пар узел / сеть-устройство, предоставив
NetDeviceContainer, Для каждого NetDevice в контейнере проверяется тип. Для каждого
устройство правильного типа (того же типа, которым управляет помощник устройства), трассировка
включено. Опять же, неявно, поскольку найденное сетевое устройство должно принадлежать
ровно один узел. Например,
NetDeviceContainer d = ...;
...
helper.EnablePcap («префикс», d);
· Вы можете включить отслеживание PCAP для набора пар узел / сеть-устройство, предоставив
Нодконтейнер. Для каждого узла в Нодконтейнер это прикреплено Сетевые устройства повторяются.
Для каждого NetDevice прикрепленный к каждому узлу в контейнере, тип этого устройства
проверил. Для каждого устройства соответствующего типа (того же типа, которым управляет устройство
помощник), трассировка включена.
Контейнер узлов n;
...
helper.EnablePcap («префикс», n);
· Вы можете включить отслеживание PCAP на основе идентификатора узла и идентификатора устройства, а также с помощью
явный Ptr. Каждый узел в системе имеет целочисленный идентификатор узла и каждое подключенное устройство.
к узлу имеет целочисленный идентификатор устройства.
helper.EnablePcap («префикс», 21, 1);
· Наконец, вы можете включить отслеживание PCAP для всех устройств в системе с одним и тем же типом
как то, что управляется помощником устройства.
helper.EnablePcapAll («префикс»);
Имена файлов
В приведенных выше описаниях методов подразумевается построение полного имени файла с помощью
способ реализации. По соглашению, трассировки PCAP в нс-3 системы имеют вид
- id> - id> .pcap
Как упоминалось ранее, каждый узел в системе будет иметь присвоенный системой идентификатор узла; и
каждое устройство будет иметь индекс интерфейса (также называемый идентификатором устройства) относительно его узла.
По умолчанию файл трассировки PCAP создается в результате включения трассировки на первом этапе.
устройство узла 21 с использованием префикса «префикс» будет префикс-21-1.pcap.
Вы всегда можете использовать нс-3 служба имен объектов, чтобы прояснить это. Например, если
вы используете службу имен объектов, чтобы назначить имя «сервер» узлу 21, в результате чего PCAP
имя файла трассировки автоматически станет, префикс-сервер-1.pcap и если вы также назначите
имя "eth0" на устройство, ваше имя файла PCAP автоматически подберет это и будет
под названием префикс-сервер-eth0.pcap.
Наконец, два метода, показанных выше,
void EnablePcap (префикс std :: string, Ptr nd, bool promiscuous = false, bool explicitFilename = false);
void EnablePcap (std :: string prefix, std :: string ndName, bool promiscuous = false, bool explicitFilename = false);
иметь параметр по умолчанию, называемый явное имя файла. Если установлено значение true, этот параметр
отключает механизм автоматического завершения имени файла и позволяет создавать явное
имя файла. Эта опция доступна только в методах, которые включают отслеживание PCAP на
одиночное устройство.
Например, чтобы организовать помощника устройства для создания единого беспорядочного PCAP
файл захвата с определенным именем мой-pcap-file.pcap на данном устройстве можно было:
Ptr nd;
...
helper.EnablePcap ("my-pcap-file.pcap", nd, true, true);
Первый правда параметр включает трассировку беспорядочного режима, а второй сообщает помощнику
интерпретировать префикс параметр как полное имя файла.
ASCII
Поведение помощника трассировки ASCII Mixin по существу похож на версию PCAP.
Взгляни на SRC / сеть / помощник / трассировка-помощник.h если вы хотите следить за обсуждением
глядя на реальный код.
Класс AsciiTraceHelperForDevice добавляет функциональность высокого уровня для использования ASCII
трассировка до вспомогательного класса устройства. Как и в случае с PCAP, каждое устройство должно реализовывать
единственный виртуальный метод, унаследованный от трассировки ASCII Mixin.
виртуальная пустота EnableAsciiInternal (Ptr ручей,
std :: string префикс,
Ptr nd,
логическое явное имя_файла) = 0;
Сигнатура этого метода отражает аппаратно-ориентированный взгляд на ситуацию на данном этапе.
уровень; а также тот факт, что помощник может писать в общий выходной поток. Все
общедоступные методы, связанные с трассировкой ASCII, унаследованные от класса AsciiTraceHelperForDevice
сократить до вызова этого единственного метода реализации, зависящего от устройства. Например,
методы трассировки ascii самого низкого уровня,
void EnableAscii (префикс std :: string, Ptr nd, bool explicitFilename = false);
void EnableAscii (Ptr поток, Ptr nd);
вызовет реализацию устройства ВключитьAsciiInternal напрямую, обеспечивая либо
действительный префикс или поток. Все другие общедоступные методы трассировки ASCII будут основываться на этих
низкоуровневые функции для обеспечения дополнительных функций пользовательского уровня. Что это значит для
пользователь указывает, что все помощники устройств в системе будут иметь все методы трассировки ASCII.
доступный; и эти методы будут работать одинаково на всех устройствах, если устройства
осуществлять EnablAsciiВнутренний правильно.
методы
void EnableAscii (префикс std :: string, Ptr nd, bool explicitFilename = false);
void EnableAscii (Ptr поток, Ptr nd);
void EnableAscii (std :: string prefix, std :: string ndName, bool explicitFilename = false);
void EnableAscii (Ptr поток, std :: string ndName);
void EnableAscii (префикс std :: string, NetDeviceContainer d);
void EnableAscii (Ptr поток, NetDeviceContainer d);
void EnableAscii (префикс std :: string, NodeContainer n);
void EnableAscii (Ptr поток, NodeContainer n);
void EnableAsciiAll (префикс std :: string);
void EnableAsciiAll (Ptr ручей);
void EnableAscii (std :: string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename);
void EnableAscii (Ptr поток, uint32_t nodeid, uint32_t deviceid);
Предлагаем вам ознакомиться с документацией по API для класса AsciiTraceHelperForDevice в
найти подробную информацию об этих методах; но подведем итог ...
· Для трассировки ASCII доступно в два раза больше методов, чем для PCAP.
отслеживание. Это потому, что в дополнение к модели в стиле PCAP, где следы от каждого
уникальная пара узел / устройство записывается в уникальный файл, мы поддерживаем модель, в которой трассировка
информация для многих пар узел / устройство записывается в общий файл. Это означает, что
- - механизм генерации имени файла заменен механизмом
обратиться к общему файлу; а количество методов API увеличено вдвое, чтобы все
комбинации.
· Как и при трассировке PCAP, вы можете включить трассировку ASCII на конкретном (узле, сетевом устройстве)
пара, предоставив Ptr к Включить Ascii метод. Ptr неявно
поскольку сетевое устройство должно принадлежать ровно одному узлу. Например,
Ptr nd;
...
helper.EnableAscii ("префикс", nd);
· Первые четыре метода также включают параметр по умолчанию, называемый явное имя файла который
работают аналогично эквивалентным параметрам в случае PCAP.
В этом случае контексты трассировки не записываются в файл трассировки ASCII, поскольку они будут
избыточный. Система выберет имя файла для создания по тем же правилам, что и
описан в разделе PCAP, за исключением того, что файл будет иметь суффикс .tr вместо
.pcap.
· Если вы хотите включить трассировку ASCII на более чем одном сетевом устройстве и отправить все трассировки
в один файл, вы также можете сделать это, используя объект для ссылки на один файл.
Мы уже видели это в приведенном выше примере cwnd:
Ptr nd1;
Ptr nd2;
...
Ptr stream = asciiTraceHelper.CreateFileStream ("имя-файла-трассировки.tr");
...
helper.EnableAscii (поток, nd1);
helper.EnableAscii (поток, nd2);
В этом случае контексты трассировки записываются в файл трассировки ASCII, поскольку они необходимы
для устранения неоднозначности следов от двух устройств. Обратите внимание: поскольку пользователь полностью
указав имя файла, строка должна включать , тр суффикс для единообразия.
· Вы можете включить трассировку ASCII для конкретной пары (узел, сетевое устройство), указав
станд :: строка представление служебной строки имени объекта для ВключитьPcap метод.
Ptr ищется из строки имени. Опять же, неявно, поскольку
названное сетевое устройство должно принадлежать ровно одному узлу. Например,
Names :: Add ("клиент" ...);
Имена :: Добавить ("client / eth0" ...);
Names :: Add ("сервер" ...);
Имена :: Добавить ("server / eth0" ...);
...
helper.EnableAscii («префикс», «клиент / eth0»);
helper.EnableAscii («префикс», «сервер / eth0»);
Это приведет к созданию двух файлов с именами prefix-client-eth0.tr и
prefix-server-eth0.tr со трассировками для каждого устройства в
соответствующий файл трассировки. Поскольку все функции EnableAscii
перегружены, чтобы принять оболочку потока, вы можете использовать эту форму как
Что ж::
Names :: Add ("клиент" ...);
Имена :: Добавить ("client / eth0" ...);
Names :: Add ("сервер" ...);
Имена :: Добавить ("server / eth0" ...);
...
Ptr stream = asciiTraceHelper.CreateFileStream ("имя-файла-трассировки.tr");
...
helper.EnableAscii (поток, «клиент / eth0»);
helper.EnableAscii (поток, «сервер / eth0»);
Это приведет к созданию единственного файла трассировки с именем имя-файла-трассировки.tr который содержит все
события трассировки для обоих устройств. События будут устранены контекстом трассировки
строки.
· Вы можете включить трассировку ASCII для коллекции пар (узел, сеть-устройство), указав
NetDeviceContainer, Для каждого NetDevice в контейнере проверяется тип. Для каждого
устройство правильного типа (того же типа, которым управляет помощник устройства), трассировка
включено. Опять же, неявно, поскольку найденное сетевое устройство должно принадлежать
ровно один узел. Например,
NetDeviceContainer d = ...;
...
helper.EnableAscii ("префикс", d);
Это приведет к созданию ряда файлов трассировки ASCII,
каждый из которых следует за - - .tr ''
условность.
Объединение всех трасс в один файл выполняется аналогично примерам.
выше:
NetDeviceContainer d = ...;
...
Ptr stream = asciiTraceHelper.CreateFileStream ("имя-файла-трассировки.tr");
...
helper.EnableAscii (поток, d);
· Вы можете включить трассировку ASCII для коллекции пар (узел, сеть-устройство), указав
Нодконтейнер. Для каждого узла в Нодконтейнер это прикреплено Сетевые устройства повторяются.
Для каждого NetDevice прикрепленный к каждому узлу в контейнере, тип этого устройства
проверил. Для каждого устройства соответствующего типа (того же типа, которым управляет устройство
помощник), трассировка включена.
Контейнер узлов n;
...
helper.EnableAscii ("префикс", n);
Это приведет к созданию ряда файлов трассировки ASCII, каждый из которых следует
- id> - id> .tr соглашение. Объединение всех следов в
single file выполняется аналогично приведенным выше примерам.
· Вы можете включить отслеживание PCAP на основе идентификатора узла и идентификатора устройства, а также с помощью
явный Ptr. Каждый узел в системе имеет целочисленный идентификатор узла и каждое подключенное устройство.
к узлу имеет целочисленный идентификатор устройства.
helper.EnableAscii ("префикс", 21, 1);
Конечно, следы можно объединить в один файл, как показано выше.
· Наконец, вы можете включить отслеживание PCAP для всех устройств в системе с одним и тем же типом
как то, что управляется помощником устройства.
helper.EnableAsciiAll («префикс»);
Это приведет к созданию нескольких файлов трассировки ASCII, по одному для каждого устройства.
в системе типа, управляемой помощником. Все эти файлы будут следовать за
- id> - id> .tr соглашение. Объединение всех следов в одну
file выполняется аналогично приведенным выше примерам.
Имена файлов
В приведенных выше описаниях методов префиксного стиля подразумевается построение полного
имена файлов по способу реализации. По соглашению, трассировка ASCII в нс-3 система
имеют форму - id> - id> .tr
Как упоминалось ранее, каждый узел в системе будет иметь присвоенный системой идентификатор узла; и
каждое устройство будет иметь индекс интерфейса (также называемый идентификатором устройства) относительно его узла.
По умолчанию файл трассировки ASCII, созданный в результате включения трассировки на первом
устройство узла 21, используя префикс «префикс», будет префикс-21-1.tr.
Вы всегда можете использовать нс-3 служба имен объектов, чтобы прояснить это. Например, если
вы используете службу имен объектов, чтобы назначить имя «сервер» узлу 21, в результате
Имя файла трассировки ASCII автоматически станет, префикс-сервер-1.tr и если вы также назначаете
имя "eth0" для устройства, ваше имя файла трассировки ASCII автоматически подберет это
и называться префикс-сервер-eth0.tr.
Некоторые методы имеют параметр по умолчанию, называемый явное имя файла. При установке на
истина, этот параметр отключает механизм автоматического завершения имени файла и позволяет вам
для создания явного имени файла. Эта опция доступна только в методах, которые принимают
префикс и включить трассировку на одном устройстве.
протокол Помощники
ПКАП
Цель этих Примеси состоит в том, чтобы упростить добавление единообразного средства трассировки PCAP в
протоколы. Мы хотим, чтобы все разновидности трассировки PCAP работали одинаково во всех
протоколы, поэтому методы этих помощников наследуются помощниками стека. Взгляни на
SRC / сеть / помощник / трассировка-помощник.h если вы хотите следить за обсуждением, глядя на
реальный код.
В этом разделе мы проиллюстрируем методы применительно к протоколу. Ipv4. К
укажите трассировки в аналогичных протоколах, просто подставьте соответствующий тип. Например,
использовать Ptr вместо Ptr и вызов ВключитьPcapIpv6 вместо ВключитьPcapIpv4.
Класс Пкапхелперфорипв4 обеспечивает функциональность высокого уровня для использования трассировки PCAP
в Ipv4 протокол. Каждый помощник протокола, включающий эти методы, должен реализовывать один
виртуальный метод, унаследованный от этого класса. Будет отдельная реализация для
Ipv6, например, но разница будет только в именах методов и сигнатурах.
Для устранения неоднозначности класса требуются разные имена методов. Ipv4 от Ipv6 которые оба
производный от класса объект, и методы, имеющие одну и ту же сигнатуру.
virtual void EnablePcapIpv4Internal (префикс std :: string,
Ptr ipv4,
uint32_t интерфейс,
логическое явное имя_файла) = 0;
Сигнатура этого метода отражает взгляд на протокол и интерфейс, ориентированный на
ситуация на этом уровне. Все общедоступные методы, унаследованные от класса Пкапхелперфорипв4
сократить до вызова этого единственного метода реализации, зависящего от устройства. Например,
метод PCAP самого низкого уровня,
void EnablePcapIpv4 (префикс std :: string, Ptr ipv4, интерфейс uint4_t, bool explicitFilename = false);
вызовет реализацию устройства Енаблепкаипв4интернал напрямую. Все остальные общественные
Методы трассировки PCAP основаны на этой реализации, чтобы обеспечить дополнительный уровень пользователя.
функциональность. Для пользователя это означает, что все помощники протокола в системе
будут доступны все методы трассировки PCAP; и все эти методы будут работать в
таким же образом через протоколы, если помощник реализует Енаблепкаипв4интернал правильно.
методы
Эти методы предназначены для взаимно-однозначного соответствия с Node- и
NetDevice- центрические версии версий устройства. Вместо Node и NetDevice пара
ограничения, мы используем ограничения протокола и интерфейса.
Обратите внимание, что, как и в версии для устройства, существует шесть методов:
void EnablePcapIpv4 (префикс std :: string, Ptr ipv4, интерфейс uint4_t, bool explicitFilename = false);
void EnablePcapIpv4 (префикс std :: string, std :: string ipv4Name, интерфейс uint32_t, bool explicitFilename = false);
void EnablePcapIpv4 (префикс std :: string, Ipv4InterfaceContainer c);
void EnablePcapIpv4 (префикс std :: string, NodeContainer n);
void EnablePcapIpv4 (std :: string prefix, uint32_t nodeid, интерфейс uint32_t, bool explicitFilename);
void EnablePcapIpv4All (префикс std :: string);
Предлагаем вам ознакомиться с документацией по API для класса Пкапхелперфорипв4 найти
подробности этих методов; но подведем итог ...
· Вы можете включить отслеживание PCAP для конкретной пары протокол / интерфейс, предоставив
Ptr и интерфейс к ВключитьPcap метод. Например,
Ptr ipv4 = узел-> GetObject ();
...
helper.EnablePcapIpv4 («префикс», ipv4, 0);
· Вы можете включить отслеживание PCAP для конкретной пары узел / сеть-устройство, предоставив
станд :: строка представление служебной строки имени объекта для ВключитьPcap метод.
Ptr ищется из строки имени. Например,
Имена :: Добавить ("serverIPv4" ...);
...
helper.EnablePcapIpv4 («префикс», «serverIpv4», 1);
· Вы можете включить отслеживание PCAP для набора пар протокол / интерфейс, предоставив
Ipv4InterfaceContainer, Для каждого Ipv4 / interface пара в контейнере протокол
Тип проверяется. Для каждого протокола соответствующего типа (того же типа, которым управляет
помощник устройства), трассировка включена для соответствующего интерфейса. Например,
Узлы NodeContainer;
...
Устройства NetDeviceContainer = deviceHelper.Install (узлы);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase («10.1.1.0», «255.255.255.0»);
Интерфейсы Ipv4InterfaceContainer = ipv4.Assign (устройства);
...
helper.EnablePcapIpv4 («префикс», интерфейсы);
· Вы можете включить отслеживание PCAP для набора пар протокол / интерфейс, предоставив
Нодконтейнер. Для каждого узла в Нодконтейнер найден соответствующий протокол.
Для каждого протокола перечисляются его интерфейсы, и в результирующем окне включается трассировка.
пары. Например,
Контейнер узлов n;
...
helper.EnablePcapIpv4 («префикс», n);
· Вы можете включить отслеживание PCAP на основе идентификатора узла и интерфейса. В этом
случае идентификатор узла переводится в Ptr и соответствующий протокол ищется
в узле. Результирующий протокол и интерфейс используются для определения результирующего
источник трассировки.
helper.EnablePcapIpv4 («префикс», 21, 1);
· Наконец, вы можете включить отслеживание PCAP для всех интерфейсов в системе с соответствующими
протокол того же типа, что и управляемый помощником устройства.
helper.EnablePcapIpv4All («префикс»);
Имена файлов
Во всех приведенных выше описаниях методов подразумевается построение полного
имена файлов по способу реализации. По соглашению, трассировки PCAP, взятые для устройств в
нс-3 системы имеют вид " - - .pcap ". В случае
трассировок протоколов, существует взаимно однозначное соответствие между протоколами и Nodes. Это
потому что протокол Объекты объединены в Узел Объекты. Поскольку нет глобального
идентификатор протокола в системе, мы используем соответствующий идентификатор узла в именовании файлов. Следовательно
существует вероятность конфликта имен файлов в автоматически выбранных именах файлов трассировки.
По этой причине соглашение об именах файлов изменено для трассировок протокола.
Как упоминалось ранее, каждый узел в системе будет иметь присвоенный системой идентификатор узла.
Поскольку существует взаимно однозначное соответствие между экземплярами протокола и экземплярами узла
мы используем идентификатор узла. Каждый интерфейс имеет идентификатор интерфейса, соответствующий его протоколу. Мы используем
конвенция " -n -я .pcap "для именования файлов трассировки в
помощники протокола.
Поэтому по умолчанию файл трассировки PCAP, созданный в результате включения трассировки на
интерфейс 1 протокола IPv4 узла 21 с использованием префикса «префикс» будет
«префикс-n21-i1.pcap».
Вы всегда можете использовать нс-3 служба имен объектов, чтобы прояснить это. Например, если
вы используете службу имен объектов, чтобы присвоить Ptr имя serverIpv4. на узле
21, имя результирующего файла трассировки PCAP автоматически станет,
«префикс-nserverIpv4-i1.pcap».
Некоторые методы имеют параметр по умолчанию, называемый явное имя файла. При установке на
истина, этот параметр отключает механизм автоматического завершения имени файла и позволяет вам
для создания явного имени файла. Эта опция доступна только в методах, которые принимают
префикс и включить трассировку на одном устройстве.
ASCII
Поведение помощников трассировки ASCII по существу аналогично случаю PCAP. Взять
смотреть на SRC / сеть / помощник / трассировка-помощник.h если вы хотите следить за обсуждением, пока
глядя на реальный код.
В этом разделе мы проиллюстрируем методы применительно к протоколу. Ipv4. К
укажите трассировки в аналогичных протоколах, просто подставьте соответствующий тип. Например,
использовать Ptr вместо Ptr и вызов ВключитьAsciiIpv6 вместо
ВключитьAsciiIpv4.
Класс AsciiTraceHelperForIpv4 добавляет функциональность высокого уровня для использования ASCII
трассировка до помощника протокола. Каждый протокол, который включает эти методы, должен реализовывать
единственный виртуальный метод, унаследованный от этого класса.
виртуальная пустота EnableAsciiIpv4Internal (Ptr ручей,
std :: string префикс,
Ptr ipv4,
uint32_t интерфейс,
логическое явное имя_файла) = 0;
Сигнатура этого метода отражает взгляд на протокол и интерфейс, ориентированный на
ситуация на этом уровне; а также тот факт, что помощник может писать в общий
выходной поток. Все общедоступные методы, унаследованные от класса
PcapAndAsciiTraceHelperForIpv4 свести к вызову этого единственного устройства, зависящего от
метод реализации. Например, методы трассировки ASCII самого низкого уровня,
void EnableAsciiIpv4 (префикс std :: string, Ptr ipv4, интерфейс uint4_t, bool explicitFilename = false);
void EnableAsciiIpv4 (Ptr поток, Ptr ipv4, интерфейс uint4_t);
вызовет реализацию устройства EnableAsciiIpv4Internal напрямую, обеспечивая либо
префикс или поток. Все другие общедоступные методы трассировки ASCII будут основываться на этих
низкоуровневые функции для обеспечения дополнительных функций пользовательского уровня. Что это значит для
пользователь указывает, что все помощники устройств в системе будут иметь все методы трассировки ASCII.
доступный; и эти методы будут работать одинаково для разных протоколов, если
протоколы реализуют EnablAsciiIpv4 Внутренний правильно.
методы
void EnableAsciiIpv4 (префикс std :: string, Ptr ipv4, интерфейс uint4_t, bool explicitFilename = false);
void EnableAsciiIpv4 (Ptr поток, Ptr ipv4, интерфейс uint4_t);
void EnableAsciiIpv4 (префикс std :: string, std :: string ipv4Name, интерфейс uint32_t, bool explicitFilename = false);
void EnableAsciiIpv4 (Ptr поток, std :: string ipv4Name, интерфейс uint32_t);
void EnableAsciiIpv4 (префикс std :: string, Ipv4InterfaceContainer c);
void EnableAsciiIpv4 (Ptr поток, Ipv4InterfaceContainer c);
void EnableAsciiIpv4 (префикс std :: string, NodeContainer n);
void EnableAsciiIpv4 (Ptr поток, NodeContainer n);
void EnableAsciiIpv4All (префикс std :: string);
void EnableAsciiIpv4All (Ptr ручей);
void EnableAsciiIpv4 (std :: string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename);
void EnableAsciiIpv4 (Ptr поток, uint32_t nodeid, интерфейс uint32_t);
Предлагаем вам ознакомиться с документацией по API для класса PcapAndAsciiHelperForIpv4 в
найти подробную информацию об этих методах; но подведем итог ...
· Для трассировки ASCII доступно в два раза больше методов, чем для PCAP.
отслеживание. Это потому, что в дополнение к модели в стиле PCAP, где следы от каждого
уникальная пара протокол / интерфейс записывается в уникальный файл, мы поддерживаем модель, в которой
информация трассировки для многих пар протокол / интерфейс записывается в общий файл. Этот
означает, что -n - механизм генерации имени файла
заменен механизмом обращения к общему файлу; а количество методов API
удвоен, чтобы разрешить все комбинации.
· Как и при трассировке PCAP, вы можете включить трассировку ASCII для определенного протокола / интерфейса.
пара, предоставив Ptr и интерфейс к Включить Ascii метод. Например,
Ptr ipv4;
...
helper.EnableAsciiIpv4 («префикс», ipv4, 1);
В этом случае контексты трассировки не записываются в файл трассировки ASCII, поскольку они будут
избыточный. Система выберет имя файла для создания по тем же правилам, что и
описано в разделе PCAP, за исключением того, что файл будет иметь суффикс ".tr" вместо
из ".pcap".
· Если вы хотите включить трассировку ASCII на более чем одном интерфейсе и отправить все трассировки
в один файл, вы также можете сделать это, используя объект для ссылки на один файл.
У нас уже есть нечто подобное в приведенном выше примере "cwnd":
Ptr протокол4 = узел1-> GetObject ();
Ptr протокол4 = узел2-> GetObject ();
...
Ptr stream = asciiTraceHelper.CreateFileStream ("имя-файла-трассировки.tr");
...
helper.EnableAsciiIpv4 (поток, протокол1, 1);
helper.EnableAsciiIpv4 (поток, протокол2, 1);
В этом случае контексты трассировки записываются в файл трассировки ASCII, поскольку они необходимы.
для устранения неоднозначности трассировки двух интерфейсов. Обратите внимание: поскольку пользователь полностью
При указании имени файла строка должна включать ", tr" для единообразия.
· Вы можете включить трассировку ASCII для определенного протокола, указав станд :: строка
представление служебной строки имени объекта для ВключитьPcap метод. Ptr is
поднял глаза от строки имени. В в результирующих именах файлов неявно, поскольку
существует взаимно однозначное соответствие между экземплярами протокола и узлами, например,
Имена :: Добавить ("node1Ipv4" ...);
Имена :: Добавить ("node2Ipv4" ...);
...
helper.EnableAsciiIpv4 («префикс», «node1Ipv4», 1);
helper.EnableAsciiIpv4 («префикс», «node2Ipv4», 1);
Это приведет к созданию двух файлов с именем «prefix-nnode1Ipv4-i1.tr» и
«prefix-nnode2Ipv4-i1.tr» с трассировками для каждого интерфейса в соответствующем файле трассировки.
Поскольку все функции EnableAscii перегружены, чтобы принимать оболочку потока, вы можете
также используйте эту форму:
Имена :: Добавить ("node1Ipv4" ...);
Имена :: Добавить ("node2Ipv4" ...);
...
Ptr stream = asciiTraceHelper.CreateFileStream ("имя-файла-трассировки.tr");
...
helper.EnableAsciiIpv4 (поток, «node1Ipv4», 1);
helper.EnableAsciiIpv4 (поток, «node2Ipv4», 1);
Это приведет к созданию единственного файла трассировки с именем "имя-файла-трассировки.tr", содержащего все
событий трассировки для обоих интерфейсов. События будут устранены следом
контекстные строки.
· Вы можете включить трассировку ASCII для набора пар протокол / интерфейс, предоставив
Ipv4InterfaceContainer. Для каждого протокола соответствующего типа (того же типа, что и
управляется помощником устройства), трассировка включена для соответствующего интерфейса.
Опять же, неявно, поскольку между каждым
протокол и его узел. Например,
Узлы NodeContainer;
...
Устройства NetDeviceContainer = deviceHelper.Install (узлы);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase («10.1.1.0», «255.255.255.0»);
Интерфейсы Ipv4InterfaceContainer = ipv4.Assign (устройства);
...
...
helper.EnableAsciiIpv4 («префикс», интерфейсы);
Это приведет к созданию ряда файлов трассировки ASCII, каждый из которых следует
в -n -я .tr соглашение. Объединение всех следов в
single file выполняется аналогично приведенным выше примерам:
Узлы NodeContainer;
...
Устройства NetDeviceContainer = deviceHelper.Install (узлы);
...
Ipv4AddressHelper ipv4;
ipv4.SetBase («10.1.1.0», «255.255.255.0»);
Интерфейсы Ipv4InterfaceContainer = ipv4.Assign (устройства);
...
Ptr stream = asciiTraceHelper.CreateFileStream ("имя-файла-трассировки.tr");
...
helper.EnableAsciiIpv4 (поток, интерфейсы);
· Вы можете включить трассировку ASCII для набора пар протокол / интерфейс, предоставив
Нодконтейнер. Для каждого узла в Нодконтейнер найден соответствующий протокол.
Для каждого протокола перечисляются его интерфейсы, и в результирующем окне включается трассировка.
пары. Например,
Контейнер узлов n;
...
helper.EnableAsciiIpv4 («префикс», n);
Это приведет к созданию ряда файлов трассировки ASCII, каждый из которых следует
в - - .tr соглашение. Объединение всех следов в
single file выполняется аналогично приведенным выше примерам.
· Вы можете включить отслеживание PCAP на основе идентификатора узла и идентификатора устройства. В этом
случае идентификатор узла переводится в Ptr и соответствующий протокол ищется
в узле. Результирующий протокол и интерфейс используются для определения результирующего
источник трассировки.
helper.EnableAsciiIpv4 («префикс», 21, 1);
Конечно, следы можно объединить в один файл, как показано выше.
· Наконец, вы можете включить трассировку ASCII для всех интерфейсов в системе с соответствующими
протокол того же типа, что и управляемый помощником устройства.
helper.EnableAsciiIpv4All («префикс»);
Это приведет к созданию нескольких файлов трассировки ASCII, по одному на каждый
интерфейс в системе, связанный с протоколом типа, управляемого помощником. Все
эти файлы будут следовать -n -я
Все трассировки в один файл выполняются аналогично приведенным выше примерам.
Имена файлов
В приведенных выше описаниях методов префиксного стиля подразумевается построение полного
имена файлов по способу реализации. По соглашению, трассировка ASCII в нс-3 система
имеют форму " - - .tr "
Как упоминалось ранее, каждый узел в системе будет иметь присвоенный системой идентификатор узла.
Поскольку существует взаимно однозначное соответствие между протоколами и узлами, которые мы используем для идентификатора узла
для идентификации протокола. Каждый интерфейс по данному протоколу будет иметь
индекс интерфейса (также называемый просто интерфейсом) относительно его протокола. По умолчанию,
затем файл трассировки ASCII, созданный в результате включения трассировки на первом устройстве
Узел 21, использующий префикс «prefix», будет «prefix-n21-i1.tr». Используйте префикс для
устранять неоднозначность нескольких протоколов на узел.
Вы всегда можете использовать нс-3 служба имен объектов, чтобы прояснить это. Например, если
вы используете службу имен объектов для присвоения имени "serverIpv4" протоколу на узле
21, а также укажите первый интерфейс, результирующее имя файла трассировки ASCII будет автоматически
превратиться в "prefix-nserverIpv4-1.tr".
Некоторые методы имеют параметр по умолчанию, называемый явное имя файла. При установке на
истина, этот параметр отключает механизм автоматического завершения имени файла и позволяет вам
для создания явного имени файла. Эта опция доступна только в методах, которые принимают
префикс и включить трассировку на одном устройстве.
Итого
нс-3 включает чрезвычайно богатую среду, позволяющую пользователям на нескольких уровнях настраивать
виды информации, которые можно извлечь из моделирования.
Существуют вспомогательные функции высокого уровня, которые позволяют пользователям просто управлять сбором
предопределенные выходные данные с высокой степенью детализации. Есть вспомогательные функции среднего уровня, позволяющие
более опытные пользователи могут настраивать способ извлечения и сохранения информации; и там
являются низкоуровневыми основными функциями, позволяющими опытным пользователям изменять систему для представления новых и
ранее неэкспортированная информация в виде, который будет немедленно доступен пользователям на
более высокие уровни.
Это очень комплексная система, и мы понимаем, что ее нужно много переварить, особенно
для новых пользователей или тех, кто не знаком с C ++ и его идиомами. Мы рассматриваем
система отслеживания очень важная часть нс-3 и поэтому рекомендую стать таким же знакомым, как
возможно с этим. Вероятно, понимание остальной части нс-3 система
будет довольно просто после того, как вы освоите систему отслеживания
ДАННЫЕ КОЛЛЕКЦИЯ
В нашей последней главе учебника представлены некоторые компоненты, которые были добавлены в нс-3 в версии
3.18, которые все еще находятся в стадии разработки. Этот учебный раздел также является
работы в прогресс.
мотивация
Одним из основных моментов при запуске моделирования является создание выходных данных либо для
в исследовательских целях или просто для ознакомления с системой. В предыдущей главе мы
представил подсистему трассировки и пример шестой.cc. от которого трассировка PCAP или ASCII
файлы создаются. Эти трассировки ценны для анализа данных с использованием различных
внешние инструменты, и для многих пользователей такие выходные данные являются предпочтительным средством сбора
данные (для анализа внешними инструментами).
Однако есть также варианты использования не только для создания файла трассировки, включая
следующие:
· Генерация данных, которые плохо сопоставляются с трассировками PCAP или ASCII, например, непакетные
данные (например, переходы конечного автомата протокола),
· Большие симуляции, для которых требования дискового ввода-вывода для создания файлов трассировки
непомерно или громоздко, и
· нужда в онлайн обработка или вычисление данных в ходе моделирования.
Хорошим примером этого является определение условия завершения моделирования, чтобы сообщить
когда остановиться, когда он получил достаточно данных, чтобы сформировать достаточно узкую уверенность
интервал вокруг оценки некоторого параметра.
Команда нс-3 структура сбора данных предназначена для предоставления этих дополнительных возможностей
помимо вывода на основе трассировки. Рекомендуем читателю, интересующемуся данной темой, проконсультироваться
нс-3 Пособие для более детального изучения этого фреймворка; здесь мы резюмируем с
пример программы некоторые развивающие возможности.
Пример Code
Пример учебного пособия примеры / учебник / седьмой.cc напоминает шестой.cc пример мы
рассмотрено ранее, за исключением нескольких изменений. Во-первых, он был включен для IPv6.
поддержка с параметром командной строки:
Командная строка командной строки;
cmd.AddValue ("useIpv6", "Использовать Ipv6", useV6);
cmd.Parse(argc, argv);
Если пользователь указывает использовать IPv6, программа будет запускаться с использованием IPv6 вместо IPv4.
Команда помощь вариант, доступный на всех нс-3 программы, которые поддерживают объект CommandLine как
показанное выше, может быть вызвано следующим образом (обратите внимание на использование двойных кавычек):
./waf - выполнить "седьмой - справка"
который производит:
ns3-dev-седьмая отладка [аргументы программы] [общие аргументы]
Аргументы программы:
--useIpv6: использовать Ipv6 [false]
Общие аргументы:
--PrintGlobals: распечатать список глобальных объектов.
--PrintGroups: распечатать список групп.
--PrintGroup = [группа]: распечатать все идентификаторы типа группы.
--PrintTypeIds: распечатать все TypeIds.
--PrintAttributes = [typeid]: распечатать все атрибуты typeid.
--PrintHelp: распечатать это справочное сообщение.
Это значение по умолчанию (использование IPv4, поскольку useIpv6 - false) можно изменить, переключив логическое значение
значение следующим образом:
./waf --run "седьмой --useIpv6 = 1"
и посмотрите на сгенерированный pcap, например, с ТСРйитр:
tcpdump -r седьмой.pcap -nn -tt
Это был небольшой экскурс в поддержку IPv6 и командную строку, которая также была
представленный ранее в этом руководстве. Для специального примера использования командной строки,
пожалуйста, посмотри SRC / ядро / примеры / command-line-example.cc.
Теперь вернемся к сбору данных. в примеры / учебник / каталог, введите следующее
команда: Разница -u шестой.cc седьмой.cc, и изучите некоторые из новых строк этого различия:
+ std :: string probeType;
+ std :: string tracePath;
+ если (используйте V6 == false)
,
...
+ probeType = "ns3 :: Ipv4PacketProbe";
+ tracePath = "/ NodeList / * / $ ns3 :: Ipv4L3Protocol / Tx";
+}
+ еще
,
...
+ probeType = "ns3 :: Ipv6PacketProbe";
+ tracePath = "/ NodeList / * / $ ns3 :: Ipv6L3Protocol / Tx";
+}
...
+ // Используйте GnuplotHelper для построения графика количества байтов пакета с течением времени
+ GnuplotHelperplotHelper;
+
+ // Настраиваем сюжет. Первый аргумент - это префикс имени файла.
+ // для сгенерированных выходных файлов. Второй, третий и четвертый
+ // аргументы - это, соответственно, заголовок графика, метки оси x и оси y
+ plotHelper.ConfigurePlot ("счетчик байтов седьмого пакета",
+ "Зависимость количества байтов пакетов от времени",
+ "Время (секунды)",
+ "Счетчик байтов пакета");
+
+ // Укажите тип зонда, путь к источнику трассировки (в пространстве имен конфигурации) и
+ // зондирование источника трассировки вывода ("OutputBytes") для построения графика. Четвертый аргумент
+ // указывает имя метки ряда данных на графике. Последний
Аргумент + // форматирует график, указывая, где должен быть размещен ключ.
+ plotHelper.PlotProbe (тип зонда,
+ трассировка,
+ "OutputBytes",
+ "Счетчик байтов пакета",
+ GnuplotAggregator :: KEY_BELOW);
+
+ // Используйте FileHelper для записи количества байтов пакета с течением времени
+ FileHelper файловый помощник;
+
+ // Настроить файл для записи и форматирование выходных данных.
+ fileHelper.ConfigureFile ("счетчик байтов седьмого пакета",
+ FileAggregator :: FORMATTED);
+
+ // Устанавливаем метки для этого отформатированного выходного файла.
+ fileHelper.Set2dFormat ("Время (секунды) =% .3e \ tPacket Byte Count =% .0f");
+
+ // Укажите тип зонда, путь зонда (в пространстве имен конфигурации) и
+ // зондирование источника трассировки вывода ("OutputBytes") для записи.
+ fileHelper.WriteProbe (тип зонда,
+ трассировка,
+ "OutputBytes");
+
Симулятор :: Стоп (Секунды (20));
Симулятор :: Беги ();
Симулятор :: Уничтожить ();
Внимательный читатель заметит при тестировании атрибута командной строки IPv6 выше,
который седьмой.cc создал ряд новых выходных файлов:
седьмой-пакет-байт-счет-0.txt
седьмой-пакет-байт-счет-1.txt
седьмой-пакет-байтов-count.dat
седьмой-пакет-байт-count.plt
седьмой-пакет-байтов-count.png
седьмой-packet-byte-count.sh
Они были созданы дополнительными операторами, представленными выше; в частности,
GnuplotHelper и FileHelper. Эти данные были получены путем подключения сбора данных
компоненты к нс-3 источники трассировки и маршалинг данных в форматированный Gnuplot и
в форматированный текстовый файл. В следующих разделах мы рассмотрим каждый из них.
GnuplotHelper
GnuplotHelper - это нс-3 вспомогательный объект, направленный на производство Gnuplot участки с
как можно меньше утверждений для общих случаев. Это крючки нс-3 отслеживать источники с данными
типы, поддерживаемые системой сбора данных. Не все нс-3 Типы данных источников трассировки:
поддерживаются, но многие из распространенных типов трассировки, включая TracedValues с обычным старым
типы данных (POD).
Давайте посмотрим на вывод этого помощника:
седьмой-пакет-байтов-count.dat
седьмой-пакет-байт-count.plt
седьмой-packet-byte-count.sh
Первый - это файл данных gnuplot с рядом временных меток, разделенных пробелами, и пакетом.
количество байтов. Мы расскажем, как был настроен этот конкретный вывод данных ниже, но давайте
продолжить с выходными файлами. Файл седьмой-пакет-байт-count.plt это сюжет gnuplot
файл, который можно открыть из gnuplot. Читатели, понимающие синтаксис gnuplot, могут
убедитесь, что в результате будет получен форматированный выходной файл PNG с именем
седьмой-пакет-байтов-count.png. Наконец, небольшой сценарий оболочки
седьмой-packet-byte-count.sh запускает этот сюжетный файл через gnuplot для получения желаемого
PNG (который можно просмотреть в графическом редакторе); то есть команда:
sh седьмой-packet-byte-count.sh
будет давать седьмой-пакет-байтов-count.png. Почему этот PNG не был создан в первую очередь
место? Ответ заключается в том, что, предоставив файл plt, пользователь может вручную настроить
результат при желании перед созданием PNG.
В заголовке изображения PNG указано, что этот график представляет собой график зависимости «Счетчик байтов пакетов от времени», и
что он строит зондируемые данные, соответствующие пути источника трассировки:
/ NodeList / * / $ ns3 :: Ipv6L3Protocol / Tx
Обратите внимание на подстановочный знак в пути трассировки. Таким образом, этот сюжет захватывает сюжет.
байтов пакета, наблюдаемых в источнике трассировки передачи объекта Ipv6L3Protocol;
в основном 596-байтовые сегменты TCP в одном направлении и 60-байтовые TCP-пакеты в другом (два
источники трассировки узлов совпали с этим источником трассировки).
Как это было настроено? Необходимо предоставить несколько утверждений. Во-первых, GnuplotHelper
объект должен быть объявлен и настроен:
+ // Используйте GnuplotHelper для построения графика количества байтов пакета с течением времени
+ GnuplotHelperplotHelper;
+
+ // Настраиваем сюжет. Первый аргумент - это префикс имени файла.
+ // для сгенерированных выходных файлов. Второй, третий и четвертый
+ // аргументы - это, соответственно, заголовок графика, метки оси x и оси y
+ plotHelper.ConfigurePlot ("счетчик байтов седьмого пакета",
+ "Зависимость количества байтов пакетов от времени",
+ "Время (секунды)",
+ "Счетчик байтов пакета");
К этому моменту настроен пустой график. Префикс имени файла является первым
аргумент, заголовок графика - второй, метка оси X - третья, а метка оси Y -
четвертый аргумент.
Следующим шагом является настройка данных, и здесь происходит подключение источника трассировки.
Во-первых, обратите внимание, что в программе мы объявили несколько переменных для дальнейшего использования:
+ std :: string probeType;
+ std :: string tracePath;
+ probeType = "ns3 :: Ipv6PacketProbe";
+ tracePath = "/ NodeList / * / $ ns3 :: Ipv6L3Protocol / Tx";
Мы используем их здесь:
+ // Укажите тип зонда, путь к источнику трассировки (в пространстве имен конфигурации) и
+ // зондирование источника трассировки вывода ("OutputBytes") для построения графика. Четвертый аргумент
+ // указывает имя метки ряда данных на графике. Последний
Аргумент + // форматирует график, указывая, где должен быть размещен ключ.
+ plotHelper.PlotProbe (тип зонда,
+ трассировка,
+ "OutputBytes",
+ "Счетчик байтов пакета",
+ GnuplotAggregator :: KEY_BELOW);
Первые два аргумента - это имя типа зонда и путь к источнику трассировки. Эти
два, вероятно, труднее всего определить, когда вы пытаетесь использовать эту структуру для построения других
следы. След зонда здесь - это Tx отследить источник класса Протокол IPv6L3, Когда мы
изучить реализацию этого класса (SRC / Интернет / модель / ipv6-l3-protocol.cc) мы можем наблюдать:
.AddTraceSource ("Tx", "Отправить пакет IPv6 на исходящий интерфейс.",
MakeTraceSourceAccessor (& Ipv6L3Protocol :: m_txTrace))
Это говорит, что Tx это имя переменной m_txTrace, который содержит декларацию:
/ **
* \ short Обратный вызов для отслеживания пакетов TX (передачи).
*/
TracedCallback , Ptr , uint6_t> m_txTrace;
Оказывается, эта конкретная подпись источника трассировки поддерживается классом Probe (что
нам здесь) класса Ipv6PacketProbe. Посмотреть файлы
src / internet / model / ipv6-packet-probe. {h, cc}.
Итак, в операторе PlotProbe выше мы видим, что оператор перехватывает трассировку.
источник (идентифицируемый строкой пути) с совпадающим нс-3 Тип зонда IPv6PacketProbe. Если
мы не поддерживали этот тип зонда (соответствующая сигнатуре источника трассировки), мы не могли
использовал этот оператор (хотя некоторые более сложные операторы нижнего уровня могли быть
используется, как описано в руководстве).
Ipv6PacketProbe сам экспортирует некоторые источники трассировки, которые извлекают данные из
зондированный объект пакета:
Идентификатор типа
Ipv6PacketProbe :: GetTypeId ()
{
статический TypeId tid = TypeId ("ns3 :: Ipv6PacketProbe")
.SetParent ()
.AddConstructor ()
.AddTraceSource ("Вывод",
«Пакет плюс его объект IPv6 и интерфейс, которые служат выходными данными для этого зонда»,
MakeTraceSourceAccessor (& Ipv6PacketProbe :: m_output))
.AddTraceSource ("Выходные байты",
"Количество байтов в пакете",
MakeTraceSourceAccessor (& Ipv6PacketProbe :: m_outputBytes))
;
вернуть tid;
}
Третий аргумент нашего оператора PlotProbe указывает, что нас интересует
количество байтов в этом пакете; в частности, источник трассировки OutputBytes для
Ipv6PacketProbe. Наконец, последние два аргумента оператора предоставляют легенду сюжета.
для этой серии данных («Счетчик байтов пакета») и необязательный оператор форматирования gnuplot
(GnuplotAggregator :: KEY_BELOW), что мы хотим, чтобы ключ графика был вставлен под графиком.
Другие варианты включают NO_KEY, KEY_INSIDE и KEY_ABOVE.
Поддержанный Прослеживать Тип
Следующие отслеживаемые значения поддерживаются зондами на момент написания этой статьи:
┌─────────────────┬─────────────────┬────────────── ────────────────────
│Тип TracedValue │ Тип зонда │ Файл │
├─────────────────┼─────────────────┼────────────── ────────────────────
│double │ DoubleProbe │ статистика / модель / double-probe.h │
├─────────────────┼─────────────────┼────────────── ────────────────────
│uint8_t │ Uinteger8Probe │ статистика / модель / uinteger-8-probe.h │
├─────────────────┼─────────────────┼────────────── ────────────────────
│uint16_t │ Uinteger16Probe │ статистика / модель / uinteger-16-probe.h │
├─────────────────┼─────────────────┼────────────── ────────────────────
│uint32_t │ Uinteger32Probe │ статистика / модель / uinteger-32-probe.h │
├─────────────────┼─────────────────┼────────────── ────────────────────
│bool │ BooleanProbe │ статистика / модель / uinteger-16-probe.h │
├─────────────────┼─────────────────┼────────────── ────────────────────
│ns3 :: Время │ TimeProbe │ stats / model / time-probe.h │
└─────────────────┴─────────────────┴────────────── ────────────────────
Следующие типы TraceSource поддерживаются Probes на момент написания этой статьи:
┌────────────────────┬──────────────────────────── ────────────┬──────────────────────────────────────── ──────────
├────────────────────┼──────────────────────────── ────────────┼──────────────────────────────────────── ──────────
├────────────────────┼──────────────────────────── ────────────┼──────────────────────────────────────── ──────────
├────────────────────┼──────────────────────────── ────────────┼──────────────────────────────────────── ──────────
├────────────────────┼──────────────────────────── ────────────┼──────────────────────────────────────── ──────────
├────────────────────┼──────────────────────────── ────────────┼──────────────────────────────────────── ──────────
└────────────────────┴──────────────────────────── ────────────┴──────────────────────────────────────── ──────────
Как видно, поддерживается только несколько источников трассировки, и все они ориентированы на
вывод размера пакета (в байтах). Однако большинство фундаментальных типов данных
доступные как TracedValues, могут поддерживаться этими помощниками.
FileHelper
Класс FileHelper - это просто вариант предыдущего примера GnuplotHelper. В
Пример программы обеспечивает форматированный вывод тех же данных с отметками времени, например:
Время (секунды) = 9.312e + 00 Количество байтов пакетов = 596
Время (секунды) = 9.312e + 00 Количество байтов пакетов = 564
Предоставляются два файла: один для узла «0» и один для узла «1», как показано на
имена файлов. Давайте посмотрим на код по частям:
+ // Используйте FileHelper для записи количества байтов пакета с течением времени
+ FileHelper файловый помощник;
+
+ // Настроить файл для записи и форматирование выходных данных.
+ fileHelper.ConfigureFile ("счетчик байтов седьмого пакета",
+ FileAggregator :: FORMATTED);
Первым аргументом является префикс файла вспомогательного файла, а следующим - спецификатор формата. Немного
другие варианты форматирования включают SPACE_SEPARATED, COMMA_SEPARATED и TAB_SEPARATED.
Пользователи могут изменять форматирование (если указано FORMATTED) с помощью строки формата
например:
+
+ // Устанавливаем метки для этого отформатированного выходного файла.
+ fileHelper.Set2dFormat ("Время (секунды) =% .3e \ tPacket Byte Count =% .0f");
Наконец, интересующий источник трассировки должен быть перехвачен. Опять же, probeType и tracePath
в этом примере используются переменные, а источник выходной трассировки зонда "OutputBytes"
на крючке:
+
+ // Укажите тип зонда, путь к источнику трассировки (в пространстве имен конфигурации) и
+ // зондирование источника трассировки вывода ("OutputBytes") для записи.
+ fileHelper.WriteProbe (тип зонда,
+ трассировка,
+ "OutputBytes");
+
Поля с подстановочными знаками в этом спецификаторе источника трассировки соответствуют двум источникам трассировки. в отличие от
Пример GnuplotHelper, в котором два ряда данных были наложены на один и тот же график, здесь два
отдельные файлы записываются на диск.
Итого
Поддержка сбора данных появилась в версии ns-3.18, а также базовая поддержка предоставления временных рядов.
вывод добавлен. Базовый паттерн, описанный выше, может быть воспроизведен в
объем поддержки существующих зондов и источников трассировки. Дополнительные возможности, в том числе
обработка статистики будет добавлена в будущих версиях.
Заключение
Фьючерсная торговля
Этот документ задуман как живой документ. Мы надеемся и ожидаем, что со временем он будет расти
охватывать все больше и больше гаек и болтов нс-3.
Написание глав руководств и учебных пособий — это не то, чем мы все восхищаемся, но это
очень важно для проекта. Если вы являетесь экспертом в одной из этих областей, пожалуйста,
рассмотрите возможность внести свой вклад в нс-3 предоставив одну из этих глав; или любую другую главу, которую вы
может считать важным.
Закрытие
нс-3 представляет собой большую и сложную систему. Невозможно охватить все, что вы
нужно будет знать в одном небольшом учебнике. Читателям, желающим узнать больше, предлагается
прочитайте следующую дополнительную документацию:
· The нс-3 руководство
· The нс-3 документация по библиотеке моделей
· The нс-3 Doxygen (документация по API)
· The нс-3 Вики
- The нс-3 Команда разработчиков.
Используйте ns-3-tutorial онлайн с помощью сервисов onworks.net