главы 1,2
глава 3
глава 4 5 Настройка
5.1 Использование модуля журналирования
5.1.1 Обзор журналирования
5.1.2 Разрешение журналирования
5.1.3 Добавление журналирования в ваш код
5.2 Использование аргументов командной строки
5.2.1 Переопределение значений атрибутов по умолчанию
5.2.2 Захват ваших собственных команд
5.3 Использование системы трассировки
5.3.1 ASCII Трассировка
Парсинг ASCII трасс
5.3.2 Трассировка PCAP Мы уже вкратце рассмотрели модуль журналирования ns‑3, просматривая скрипт first.cc. В этой главе мы более пристально присмотримся к возможным вариантам использования подсистемы журналирования. Многие большие системы поддерживают какое-то средство регистрации сообщений, и ns‑3 не является исключением. В некоторых случаях, в «консоль оператора» (которая обычно является stderr в системах на основе Unix) записываются только сообщения об ошибках. В других системах, могут выводиться предупреждающие сообщения, а также более подробная информация. В некоторых случаях, средства журналирования используются для вывода отладочных сообщений, которые могут быстро «замылить» вывод. Подхрд, используемый в ns‑3, предполагает, что все эти уровни информативности полезны, и мы предоставляем избирательный, многоуровневый подход к регистрации сообщений. Журналирование может быть полностью отключено, включено для отдельных компонентов или в глобальном масштабе. Для этого служат настраиваемые уровни информативности. Модуль журналирования ns‑3 обеспечивает относительно простой способ получения полезной информации из вашей симуляции. Вы должны понимать, что мы предоставляем механизм общего назначения — трассировку — для извлечения данных из ваших моделей, который должен быть предпочтительным для вывода при моделировании (для получения более подробной информации о нашей системы трассировки см. раздел учебника 5.3). Журналирование должно быть предпочтительным методом получения отладочной информации, предупреждений, сообщений об ошибках или для быстрого вывода сообщений из ваших сценариев или моделей в любой момент. В настоящее время в системе определено семь уровней (типов) сообщений журнала по возрастанию информативности. Мы также предоставляем макрос безусловного журналирования, который отображается всегда, независимо от уровня ведения журнала или компонента выбор. Каждый уровень может быть запрошен по отдельности или кумулятивно. Журналирование можно настроить с помощью переменной sh-среды NS_LOG или путем регистрации вызова системной функции. Как было показано ранее, система журналирования имеет Doxygen-документацию и сейчас самое время её просмотреть, если вы это еще не сделали. Теперь, когда вы прочитали документацию очень подробно, давайте воспользуемся этими знаниями, чтобы получить некоторые интересную информацию из примера сценария scratch/myfirst.cc, который вы уже компилировали. Давайте используем переменную окружения NS_LOG, чтобы запустить еще несколько журналов, но сначала, просто для того, чтобы сориентироваться, запустите последний скрипт, как вы делали ранее, Вы должны увидеть уже знакомый вывод первой программы-примера ns‑3 Оказывается, что «отправленные» и «полученные» сообщения, которые вы видите выше, на самом деле это зарегистрированные сообщения от UdpEchoClientApplication и UdpEchoServerApplication. Например, мы можем попросить клиентское приложение, распечатать дополнительную информацию, установив ее уровень журналирования через переменную окружения NS_LOG. С этого момента я собираюсь предположить, что вы используете sh-подобную оболочку, которая использует синтаксис «VARIABLE = value». Если вы используете csh-подобную оболочку, тогда вам придется преобразовать мои примеры в синтаксис «переменное значение setenv» требуется этими оболочками. В данный момент, приложение UDP эхо-клиента отвечает на следующую строку кода в scratch/myfirst.cc, Она активирует уровень журналирования LOG_LEVEL_INFO. Когда мы передаем флаг уровня журналирования, мы на самом деле включаем данный уровень и все более низкие уровни. В данном случае мы включили NS_LOG_INFO, NS_LOG_DEBUG, NS_LOG_WARN и NS_LOG_ERROR. Мы можем повысить уровень журналирования и получить больше информации, без изменений скрипта и перекомпиляция, путем установки переменной окружения NS_LOG следующим образом: Так мы устанавливаем следующее значение переменной NS_LOG sh-оболочки, Левая часть присвоения — это имя журналируемого компонента, который мы хотим настроить, а правая часть — это флаг, который мы хотим для этого применить. В данном случае мы собираемся включить в приложении все уровни отладки. Если вы запустите скрипт с установленной таким образом NS_LOG, система журналирования ns‑3 примет изменения и вы должны увидеть следующий вывод: Дополнительная отладочная информация, предоставляемая приложением, теперь соответствует уровню NS_LOG_FUNCTION. Он показывает каждый случай вызова функций во время выполнения скрипта. Как правило, в функциях-методах предпочтительно использовать (как минимум)NS_LOG_FUNCTION (this). Используйте NS_LOG_FUNCTION_NOARGS ()
только в статических функциях. Тем не менее, обратите внимание, что в системе ns‑3 нет требований поддерживать какую-либо функциональность журналирования. Решение о том, сколько информации регистрируется, остается индивидуально за разработчиком модели. В случае эхо-приложений доступно большое количество выходных данных для журналирования. Теперь вы можете просмотреть журнал вызовов функций, которые были сделаны приложением. Если вы приглядитесь внимательно, то заметите двоеточие между строкой UdpEchoClientApplication и именем метода, в том месте, где вы возможно ожидали увидеть оператор области видимости C++ (: :). Это сделано намеренно. На самом деле это не имя класса, а имя компонента журналирования. Когда есть соответствие между исходным файлом и классом, обычно это имя класса, но вы должны понимать, что на самом деле это не имя класса, и там одно двоеточие вместо двойной двоеточия. Это способ помочь вам относительно тонким способом концептуально отделить имя компонента журналирования от имени класса. Тем не менее, в некоторых случаях бывает сложно определить, какой метод на самом деле генерирует сообщение журнала. Если вы посмотрите на текст выше, то у вас возникнет вопрос, откуда взялась строка «Received 1024 bytes from 10.1.1.2». Вы можете решить эту проблему, установив уровень prefix_func в переменную окружения NS_LOG. Попробуй сделать следующее, Обратите внимание, что кавычки необходимы, поскольку вертикальная черта, которую мы используем для обозначения операции ИЛИ, также является соединителем конвейеров Unix. Теперь, если вы запустите сценарий, вы увидите, что система журналирования гарантирует, что каждое сообщение из данного журнала имеет префикс с именем компонента. Теперь вы можете видеть, что все сообщения, поступающие от приложения UDP эхо-клиента, идентифицированы как таковые. Сообщение «Received 1024 bytes from 10.1.1.2» теперь четко определено как поступающее от приложения эхо-клиента. Оставшееся сообщение должно поступить из приложения UDP эхо-сервера. Мы можем включить этот компонент, введя список компонентов, разделенных двоеточиями, в переменной среды NS_LOG. Предупреждение: в приведенном выше примере текста вам нужно будет удалить символ новой строки после двоеточия (:), он использован для форматирования документа. Теперь, если вы запустите сценарий, вы увидите все сообщения журнала из клиентского и серверного эхо-приложений. Вы может увидеть, что это может быть очень полезно при отладке. Также иногда полезно иметь возможность видеть время моделирования, в которое было создано сообщение журнала. Вы можешь сделать это путем добавления по ИЛИ бита prefix_time: Опять же, вам придется удалить выше символ новой строки. Если вы теперь запустите скрипт, то должны увидеть следующий вывод: Обратите внимание, что конструктор для UdpEchoServer был вызван во время симуляции 0 секунд. Это на самом деле происходит до начала симуляции, но это время отображается как ноль секунд. То же самое верно для сообщение конструктора UdpEchoClient. Напомним, что скрипт scratch/first.cc запустил приложение эхо-сервера за одну секунду до начала симуляции. Теперь вы можете видеть, что метод StartApplication сервера фактически вызывается на первой секунде. Вы также можете заметить, что эхо-клиент запускается на второй секунде симуляции, как мы и просили в скрипте. Теперь вы можете следить за ходом симуляции по вызову ScheduleTransmit в клиенте, который вызывает Send обратного вызова HandleRead в приложении эхо-сервера. Обратите внимание, что истекшее время для отправки пакета через двухточечный линк составляет 3,69 миллисекунды. Видно, что эхо-сервер регистрирует сообщение о том, что он отозвался на пакет, а затем, после задержки канала, вы видите, что эхо-клиент получает эхо-пакет в своем методе HandleRead. В этой симуляции многое происходит незаметно для вас. Но вы можете очень легко отследить весь процесс, включив в системе все компоненты журналирования. Попробуйте установить в переменной NS_LOG следующее значение, Звездочка выше является подстановочным символом компонента журналирования. Это включит все записи во всех компонентах используется в симуляции. Я не буду воспроизводить вывод здесь (на момент написания статьи он производит 1265 строк вывода для один эхо-пакет), но вы можете перенаправить эту информацию в файл и просмотреть его в вашем любимом редакторе, Я лично использую эту чрезвычайно многословную версию ведения журнала, когда у меня возникла проблема, и я понятия не имею, где дела пошли не так. Я могу довольно легко следить за выполнением кода, не устанавливая точки останова и пошаговый код в отладчике. Я могу просто отредактировать вывод в моем любимом редакторе и искать то, что я ожидаю, и видеть, что происходит то, чего не ожидал. Когда у меня есть общее представление о том, что идет не так, я перехожу в отладчик для детального изучения проблемы. Этот вид вывода может быть особенно полезен, когда ваш скрипт делает что-то совершенно неожиданное. Если вы пользуетесь только отладчиком, вы можете полностью пропустить неожиданный поворот. Регистрация делает такие повороты заметными. Вы можете добавить новые записи в свои симуляции, совершая вызовы компонента log из нескольких макросов. Давайте сделаем это в сценарии myfirst.cc, который мы имеем в «чистой» директории. Напомним, что мы определили в этом сценарии компонент журналирования: Вам известно, что вы можете включить журналирование всех сообщений этого компонента, установив переменную среды NS_LOG на разных уровнях. Давайте продолжим и добавим некоторые записи в скрипт. Макрос, используемый для добавления в журнал сообщений информационного уровня — NS_LOG_INFO. Давайте добавим сообщение (непосредственно перед тем, как мы начнем создавать узлы), которое говорит вам, что сценарий находится на этапе создания топологии ("Creating Topology"). Это делается в следующем фрагменте кода,
Откройте scratch/myfirst.cc в вашем любимом редакторе и добавьте строку,
NS_LOG_INFO ("Creating Topology");
прямо перед строками, Теперь скомпилируйте скрипт, используя waf, и очистите переменную NS_LOG, чтобы отключить поток журналирования, который мы включили ранее: вы не увидите новое сообщение, так как связанный с ним компонент журналирования (FirstScriptExample) не был включен. Чтобы увидеть ваше сообщение, вам нужно включить компонент ведения журнала FirstScriptExample с уровнем не ниже NS_LOG_INFO. Если вы просто хотите увидеть этот конкретный уровень ведения журнала, вы можете включить его так, Если вы сейчас запустите скрипт, то увидите новое сообщение «Creating Topology», Другой способ изменить поведение сценариев ns‑3 без редактирования и сборки — использование аргументов командной строки. Мы предоставляем механизм для разбора аргументов командной строки и автоматической установки локальных и глобальных переменных на основе результатов. Первым шагом в использовании системы аргументов командной строки является объявление синтаксического анализатора командной строки. Это сделать довольно просто (в вашей основной программе), как в следующем коде, Этот простой двухстрочный фрагмент на самом деле очень полезен сам по себе. Он открывает дверь к глобальной переменной ns‑3 и системе атрибутов. Давайте добавим две строки кода в начало главной функции скрипта scratch/myfirst.cc. Двигаясь дальше, компилируем сценарий и запускаем его, при запуске делаем запрос справки следующим образом, Эта команда попросит Waf запустить скрипт scratch/myfirst и передать ему аргумент командной строки --PrintHelp. Кавычки необходимы, чтобы показать, для какой программы предназначен аргумент. Парсер командной строки обнаружит аргумент --PrintHelp и выведет ответ, Теперь рассмотрим опцию --PrintAttributes. Мы уже упоминали систему атрибутов ns‑3, при изучении скрипта first.cc. Мы видели следующие строки кода, и говорили, что DataRate на самом деле является атрибутом PointToPointNetDevice. Давайте применим синтаксический анализатор аргументов командной строки для просмотра атрибутов PointToPointNetDevice. Список помощи говорит, что мы должны предоставить TypeId. Это имя класса, к которому принадлежат интересующие атрибуты. В нашем случае это будет ns3::PointToPointNetDevice. Продолжим двигаться вперед, введите, Система распечатает все атрибуты этого типа сетевого устройства. Вы увидите, что среди атрибутов в списке есть, Это значение по умолчанию, которое будет использоваться в системе при создании объекта PointToPointNetDevice. Мы переопределим это значение по умолчанию с помощью параметра Attribute в PointToPointHelper выше. Давайте использовать значения по умолчанию для точка-точка устройств и каналов. Для этого удалим вызовы SetDeviceAttribute и SetChannelAttribute из myfirst.cc, который мы имеем в чистой директории. Ваш скрипт должен теперь просто объявить PointToPointHelper и не выполнять никаких операций по установке, как показано в примере ниже, Продолжайте и создайте новый скрипт с Waf (./waf) и давайте вернемся назад и включим некоторую запись из UDP эхо-приложения сервера и включим префикс времени. Если вы запустите скрипт, то должны увидеть следующий вывод: Напомним, что в прошлый раз, когда мы смотрели по времени симуляции, момент получения пакета эхо-сервером, это было в 2,00369 секунд. Теперь он получает пакет в 2.25732 секунды. Это потому, что мы просто сбросили скорость передачи данных PointToPointNetDevice с пяти мегабит в секунду до значения по умолчанию, которое составляет 32768 бит в секунду. Если бы мы подставили новый DataRate с помощью командной строки, мы могли бы снова ускорить наше моделирование. Мы сделаем это следующим образом, согласно формуле, подразумеваемой элементом справки: В результате значение атрибута DataRate по умолчанию вернется к пяти мегабитам в секунду. Вы удивлены результатом? Оказывается, чтобы вернуть исходное поведение сценария, нам нужно также установить задержку канала соответствующую скорости света. Мы можем попросить систему командной строки распечатать атрибуты канала, также как мы делали для сетевого устройства: Мы обнаружим, что атрибут задержки канала установлен следующим образом: Затем мы можем через систему командной строки установить оба этих значения по умолчанию , в этом случае мы восстанавливаем время, которое у нас было, когда мы явно установили DataRate и Delay в сценарии: Обратите внимание, что пакет снова получен сервером через 2,00369 секунд. Мы могли бы на самом деле установить таким образом любой из используемых в сценарии атрибутов. В частности, мы могли бы установить отличные от единицы значения атрибутов MaxPackets UdpEchoClient. Как бы вы использовали это? Попробуйте. Помните, что вы должны закомментировать место, где мы переопределяем значение атрибута по умолчанию и явно установить MaxPackets в сценарии. Затем вы должны пересобрать скрипт. Вы также можете средствами командной строки получить справку о синтаксисе для установки нового значения атрибута по умолчанию. Разобравшись в этом вы сможете управлять количеством пакетов, отображаемых в командной строке. Поскольку мы прилежные люди, то наша командная строка должна выглядеть примерно так: Естественный вопрос, который возникает в этой месте, состоит в том, как узнать о существовании всех этих атрибутов. Опять же, система командной строки имеет функцию помощи в этом вопросе. Если мы запросим помощь командной строки, то мы должны увидеть: Если вы выберете аргумент «PrintGroups», то должны увидеть список всех зарегистрированных групп TypeId. Имена групп согласуются с именами модулей в исходной директории (хотя и с заглавной буквы). Распечатка всей информации сразу будет слишком объемной, поэтому доступен дополнительный фильтр для печати информации по группам. Так, снова фокусируясь на модуле «точка-точка»: Здесь можно найти доступные имена TypeId для поиска атрибутов, например, в
--PrintAttributes = ns3 :: PointToPointChannel, как показано выше. Еще один способ узнать об атрибутах — через Doxygen ns‑3. Там есть страница, которая перечисляет все зарегистрированные в симуляторе атрибуты. Вы также можете через систему командной строки добавить свои собственные хуки. Это делается довольно просто с помощью метод парсера командной строки AddValue.
Давайте используем этой возможность, чтобы указать количество пакетов, которые должны отображаться, совершенно другим способом. Давайте добавим локальную переменную с именем nPackets в функцию main. Мы установим её в единицу, чтобы соответствовать нашему предыдущему поведению по умолчанию. Чтобы позволить парсеру командной строки, изменить это значение, нам нужно захватить это значение в парсер. Мы делаем это, добавив вызов AddValue. Перейдите и измените скрипт scratch/myfirst.cc так, чтобы начать со следующего кода, Прокрутите вниз до точки в скрипте, где мы устанавливаем атрибут MaxPackets и измените его так, чтобы он был настроен на переменную nPackets вместо константы 1, как показано ниже. Теперь, если вы запустите скрипт и подставите аргумент --PrintHelp, вы должны увидеть новый аргумент пользователя. перечисленный на дисплее справки. Введите, Если вы хотите изменить количество передаваемых пакетов, вы можете сделать это, установив в командной строке аргумент - -nPackets, Теперь вы должны теперь увидеть Вы теперь оправили два пакета. Довольно просто, не правда ли?
Вы можете видеть, что как пользователь ns‑3, вы можете использовать систему аргументов командной строки для управления глобальными значениями и атрибутами. Если вы автор модели, вы можете добавить новые атрибуты к вашим объектам, и они будут автоматически доступны для настройки вашими пользователями через систему командной строки. Если вы автор сценария, вы можете добавлять новые переменные в ваши скрипты и безболезненно подключать их к системе командной строки. Весь смысл моделирования заключается в создании выходных данных для дальнейшего изучения, а система трассировки ns‑3 является основным механизмом для этого. Поскольку ns‑3 — это программа на C++, то могут быть использованы стандартные средствами генерации выходных данных программы на C++ : Вы даже можете использовать модуль журналирования, чтобы добавить небольшую структуру в ваше решение. Известно много проблем порождаемых таким подходом и поэтому для решения этих проблем мы предоставили общую подсистему трассировки событий. Основные цели системы трассировки ns‑3: Для базовых задач система трассировки должна позволять пользователю генерировать стандартную трассировку для популярных источников, и выбирать объекты генерируют трассировку; Промежуточные пользователи должны иметь возможность расширять систему трассировки для изменения генерируемого выходного формата или для вставки новых источников трассировки, без модификации ядра симулятора; Опытные пользователи могут модифицировать ядро симулятора для добавления новых источников и приемников трассировки. Система трассировки ns‑3 построена на принципах независимых источников отслеживания и приемников, а также унифицированном механизме подключения источников к потребителям. Система трассировки ns-3 построена на принципах независимых источников и приемников трассировки, а также унифицированной механизм подключения источников к приемникам. Источниками трассировки являются объекты, которые могут сигнализировать о событиях, происходящих в симуляции и обеспечить доступ к интересующим базовым данным. Например, источник трассировки может указывать, когда сетевое устройство получило пакет и обеспечивает доступ к содержимому пакета для заинтересованных приемников трассировки. Источники трассировки сами по себе бесполезны, если они не «связаны» с другими частями кода, которые на самом деле делают с информацией, предоставленной приемником, что-то полезное. Трассировщики являются потребителями событий и данных, предоставленных источниками трассировки. Например, можно создать приемник трассировки, который будет (при подключении к источнику трассировки предыдущего пример) выводить на печать интересующие части полученного пакета. Разумное основание для такого явного разделения состоит в том, чтобы позволить пользователям подключать новые типы приемников к существующим источникам трассировки без необходимости редактирования и перекомпиляции ядра симулятора. Таким образом, в приведенном выше примере пользователь может определить новый трассировщик в своем скрипте и подключить его к существующему источнику трассировки, определенному в ядре симуляции, только редактируя пользовательский скрипт. В этом руководстве мы пройдемся по некоторым предопределенным источникам и приемникам и покажем, как их можно настроить с наименьшими усилиями со стороны пользователя. См. Руководство ns‑3 или разделы с инструкциями для получения информации о расширенной конфигурации трассировки, включая расширение пространства имен трассировки и создание новых источников трассировки. ns‑3 обеспечивает вспомогательный функционал, который предоставляет низкоуровневую систему трассировки, чтобы помочь вам с деталями, при настройке несложных трассировок пакетов. Если вы включите эту функцию, вы увидите выходные данные в файлах ASCII. Для тех, кто знаком с выводом ns-2, этот тип трассировки аналогичен out.tr, который сгенерирован множеством скриптов. Давайте перейдем к делу и добавим некоторые результаты ASCII трассировки в наш скрипт scratch/myfirst.cc. Прямо перед вызовом Simulator :: Run (), добавьте следующие строки кода:
AsciiTraceHelper ascii; Как и во многих других идиомах ns‑3, этот код использует вспомогательный объект для создания трассировок ASCII. Вторая строка содержит два вложенных вызова метода. Метод «внутри» CreateFileStream () использует идиому анонимного объекта для создания объекта потока файлов в стеке (без имени объекта) и передает его вызываемому методу. В будущем мы углубимся в этот вопрос, но все, что вам нужно знать на этом этапе, это то, что вы создаете объект, представляющий файл с именем myfirst.tr и передать его в ns‑3. Мы возлагаем на ns‑3, заботу о созданном объекте на все время его жизни, в ходе которой решаются проблемы, вызванных малоизвестным (преднамеренным) ограничением связанным с копирующими конструкторами потоковых объектов C++. Внешний вызов EnableAsciiAll() сообщает помощнику, что вы хотите включить в вашей симуляции ASCII трассировку для всех соединений устройства точка-точка и то, что вы хотите, чтобы (указанные) приемники трассировки записывали информацию о перемещении пакетов в формате ASCII. Для тех, кто знаком с ns-2, отслеживаемые события эквивалентны известным точкам трассировки, которые журналируют события «+», «-», «d» и «r».
Теперь вы можете собрать скрипт и запустить его из командной строки: Как много раз до этого, вы увидите несколько сообщений от Waf, а затем “‘build’ finished successfully” (сборка завершена успешно) с некоторым количеством сообщений от работающей программы. При работе, программа создаст файл с именем myfirst.tr. Из-за особенностей работы Waf, по умолчанию файл создается не в локальной директории, а в директории верхнего уровня репозитория. Если вы хотите изменить путь, где сохраняются трассы, то чтобы указать его вы можете использовать для Waf параметр --cwd. Мы этого не сделали, то чтобы взглянуть на файл ASCII трассировки myfirst.tr в вашем любимом редакторе, нам потребуется перейти в директорию верхнего уровня нашего репозитория. Там очень много информации в довольно плотной форме, но первое, на что нужно обратить внимание, так это то, что файл состоит из отдельных строк. Это станет отчетливо видно, если вы развернете окно просмотра пошире. Каждая строка в файле соответствует событию трассировки. В данном случае мы трассируем события в очереди передачи, присутствующей в каждом сетевом устройстве точка-точка в симуляции. Очередь передачи — это очередь, через которую должен пройти каждый пакет для канала точка-точка. Обратите внимание, что каждая строка в файле трассировки начинается с одиночного символа (и имеет пробел после него). Этот символ будет иметь следующее значение: +: в очереди устройства произошла операция постановки в очередь;
-: в очереди устройства произошла операция извлечения элемента;
d: пакет был отброшен, как правило, потому, что очередь заполнена;
r: пакет был получен сетевым устройством. Давайте более детально рассмотрим первую строку в файле трассировки. Я разобью её на части (с отступами для наглядности) и номером строки слева: Первый раздел этого расширенного события трассировки (строка 0) — это операция. У нас здесь символ +, что соответствует операции постановки в очередь на передачу. Второй раздел (строка 1) — время моделирования, выраженное в секундах. Вы можете вспомнить, что мы попросили UdpEchoClientApplication начать отправку пакетов через две секунды. Здесь мы видим подтверждение того, что это действительно происходит. В следующем разделе примера трассировки (со строки 2) показывается, какой источник трассировки породил это событие (указывается трассировка пространства имен). Вы можете представлять пространство имен трассировки примерно так же, как пространстве имен файловой системы. Корнем пространства имен является NodeList. Это соответствует контейнеру, управляемому в основном коде ns‑3. В нем содержатся все узлы, которые создаются в скрипте. Так же, как файловая система может иметь в корне директории, в NodeList у нас может быть множество узлов. Таким образом, строка /NodeList/0 ссылается на нулевой узел в NodeList, который мы обычно понимаем как «узел 0». В каждом узле есть список устройств, которые были установлены. Этот список расположен следующим в пространстве имен. Вы можете видеть, что это событие трассировки исходит из DeviceList/0, который является устройством нулевым установленным в узле. Следующая подстрока, $ ns3 :: PointToPointNetDevice, сообщает, какое устройство находится в нулевой позиции: списка устройств нулевого узла. Напомним, что операция +, находящаяся в строке 0, означала, что в очереди передачи устройства произошло добавление элемента. Это отражено в последних сегментах «пути трассы»: TxQueue/Enqueue. Остальные разделы в трассировке должны быть достаточно понятны интуитивно. Строки 3-4 указывают, что пакет инкапсулирован в протоколе точка-точка. Строки 5-7 показывают, что пакет имеет заголовок версии IP4 и возник в IP-адресе 10.1.1.1 и предназначен для 10.1.1.2. Строки 8-9 показывают, что этот пакет имеет заголовок UDP и, наконец, строка 10 показывает, что полезная нагрузка — ожидаемые 1024 байта. Следующая строка в файле трассировки показывает, что тот же пакет был извлечен из очереди передачи на том же узле. Третья строка в файле трассировки показывает, что пакет принят сетевым устройством на узле с эхо-сервером. Я воспроизвел это событие ниже. Обратите внимание, что операция трассировки теперь r, а время симуляции увеличено до 2,25732 секунд. Если вы внимательно следовали инструкциям учебника, то это означает, что вы оставили DataRate сетевых устройств и задержку канала в их значениях по умолчанию. Это время должно быть знакомо, как вы уже видели в предыдущем разделе. Запись пространства имен источника трассировки (строка 2) была изменена, чтобы отразить, что это событие исходит от узла 1 (/NodeList/1) и пакет принят источником трассировки (/MacRx). Вам должно быть довольно легко отследить за движением пакета через топологию, просматривая оставшиеся в файле трассы. Помощники устройств ns‑3 также можно использовать для создания файлов трассировки в формате .pcap. Акроним pcap (обычно пишется в нижнем регистре) обозначает захват пакетов и фактически является API, который включает определение формата файла .pcap. Наиболее популярной программой, которая может читать и отображать этот формат, является Wireshark (ранее называвшаяся Ethereal). Тем не менее, есть много анализаторов трассировки трафика, которые используют этот формат пакета. Мы рекомендуем пользователям использовать множество инструментов, доступных для анализа pcap трасс. В этом руководстве мы сосредоточимся на просмотре pcap трасс с помощью tcpdump. Включение pcap трассировки, выполняется одной строкой кода. Вставьте эту строку кода после кода трассировки ASCII, который мы только что добавили в scratch/myfirst.cc. Обратите внимание, что мы передали только строку «myfirst», а не «myfirst.pcap» или что-то подобное. Это потому, что параметр это префикс, а не полное имя файла. Во время симуляции помощник фактически создаст файл трассировки для каждого устройства точка-точка. Имена файлов будут построены с использованием префикса, номера узла, номера устройства и суффикса «.pcap». Для нашего примера сценария мы в конечном итоге увидим файлы с именами «myfirst-0-0.pcap» и «myfirst-1-0.pcap», которые являются pcap трассировками для узла 0-устройство 0 и узла 1-устройство 0 соответственно. После того, как вы добавили строку кода для включения pcap трассировки, вы можете запустить скрипт обычным способом: Если вы посмотрите в директорию верхнего уровня вашего дистрибутива, вы должны увидеть три файла: файл ASCII трассировки myfirst.tr, который мы перед этим изучили, файлы myfirst-0-0.pcap и myfirst-1-0.pcap — новые pcap файлы, которые мы только что сгенерировали. На данный момент для просмотра файлов pcap проще всего будет использовать tcpdump. В дампе myfirst-0-0.pcap (клиентское устройство) вы можете видеть, что эхо-пакет отправляется через 2 секунды симуляции. Если вы посмотрите на второй дамп (myfirst-1-0.pcap), вы увидите, что пакет принимается в момент 2,257324 секунды. Вы увидите во втором дампе, что пакет возвращается в момент 2.257324 секунды, и, наконец, что пакет был получен клиентом обратно в первом дампе в момент 2.514648 секунд. Если вы не знакомы с Wireshark, есть веб-сайт, с которого вы можете скачать программы и документацию: http://www.wireshark.org/. Wireshark — это графический интерфейс пользователя, который можно использовать для отображения этих файлов трассировки. Если у вас есть Wireshark, вы можете открыть любой из файлов трассировки и отобразить содержимое, как если бы вы захватили пакеты, используя анализатор пакетов. Разработчик ПО для радиосвязи