Глава 9. Разработка сценариев

Прежде чем мы приступим к разработке сценариев, использующих модуль Satellite, разберем их общую схему построения. Она состоит из четырех шагов:

  1. Инициализация параметров данными из файла конфигурации, сцены эксперимента и командной строки. 

  2. Создание сетевой топологии (спутники, шлюзы, терминалы и т.п.). 

  3. Настройка на узлах сети приложений для генерации и приема трафика. 

  4. Запуск симуляции и сбор результатов. 

9.1 Параметры модели, доступные пользователю

Для пользователя доступно 5 групп параметров модели:

  1. Сцена (файлы в директориях data/scenarios/...)

    Это основной способ управлять геометрией и топологией эксперимента, описание сцены включает следующие файлы:

    • positions/tles.txt — орбиты спутников (TLE); 

    • positions/sat_traces.txt —траектории спутников, которые заданы временными последовательностями их координат - трассами (traced-спутники); 

    • positions/ut_positions.txt, gw_positions.txt — позиции UT/GW; 

    • positions/isls.txt — межспутниковые линии связи; 

    • beams/fwdConf.txt, rtnConf.txt — конфигурация лучей/частот/GW; 

    • waveforms/waveforms.txt, default_waveform.txt — конфигурация волновых форм (waveform/modcod);

    • standard/standard.txt — используемый при симуляции стандарт (DVB/LoRa)

    • antennapatterns/* + GeoPos.in — диаграммы направленности антенн (геометрия лучей). 

    Структура этих файлов описана в разделе  9.2.

  2. Глобальные параметры симуляции (задаваемые через Config::SetDefault / SimulationHelper

    • SimTime время симуляции; 

    • BeamsIDs, SetBeamSet/SetBeams активные лучи; 

    • UtCountPerBeam, UserCountPerUt, GwUsers число UT и пользователей; 

    • HandoversEnabled — разрешение хэндовера. 

  3. Канал и среда распространения 

    Можно управлять следующими параметрами канала:

    • Модель замираний:

      • FADING_OFF 

      •  FADING_TRACE

      •  FADING_MARKOV

    • Модель задержки (PropagationDelayModel):

      • ConstantSpeed

      • Constant 

    • включение внешних файлов описания замираний и мощности принимаемого сигнала; 

    • режим пересылки канала (ForwardingMode); 

    • параметры интерференции при произвольном доступе: RA collision/interference model и т.д. 

  4. PHY/радиопараметры узлов 

    Ниже приведены имена атрибутов из TypeId::AddAttribute(…), которые можно задавать через Config::SetDefault(“ns3::::”, …).

    Общие PHY-параметры (для UT/GW/Orbiter, где поддерживаются)

    RandomAccessAverageNormalizedOfferedLoadMeasurementWindowSize это параметр сглаживания для динамического управления нагрузкой произвольного доступа (RA dynamic load control).

  5. Трафик и протоколы 

    • Типы трафика:

      • LORA_PERIODIC

      • LORA_CBR

      • CBR

      • ONOFF

      • HTTP

      • NRTV

      • POISSON

      • VOIP

      • CUSTOM 

    • Доступные транспортные протоколы:

      • UDP

      • TCP 

В конфигурации SatTrafficHelperConf дополнительно доступен вариант: PROTOCOL_BOTH (ставит и TCP, и UDP).

  • Направления трафика:

    • RTN_LINK (обычно UT→GW);

    • FWD_LINK (обычно GW→UT); 

В SatTrafficHelperConf дополнительно доступен вариант BOTH_LINK.

  • Для VoIP — доступные кодеки:

    • G_711_1

    • G_711_2

    • G_723_1

    • G_729_2

    • G_729_3 

9.2 Сцена эксперимента

Сцена эксперимента — это описание физического расположения устройств участвующих в эксперименте, параметров используемых лучей спутника и используемых при передаче стандартов.

Для каждой сцены создается своя директория с соответствующим названием, она содержит следующие поддиректории:

antennapatterns символическая ссылка на директорию с диаграммами направленности антенн. Исходная директория расположена в data/additional-input/antennapatterns

beams конфигурационные файлы для прямого и обратного каналов, используемые для описания лучей.

beamhopping конфигурационные файлы для переключения лучей (beam hopping). Переключение лучей используется только если эта папка присутствует.

positions содержит позиции GW и UT (дополнительные UT могут быть добавлены через SimulationHelper и GroupHelper). Содержит также описание положения спутника: либо положение геостационарного спутника (GEO), либо TLE + список ISL + дата начала моделирования.

standard  используемый стандарт. Может быть либо DVB, либо LORA.

waveforms содержит список всех форм сигналов (waveforms), используемых на обратном канале. Она должна содержать файл waveforms.txt, который описывает все формы сигналов, и файл default_waveform.txt, который содержит ID формы сигнала по умолчанию.

Рассмотрим форматы файлов, которые содержатся в этих поддиректориях.

Поддиректория antennapatterns

В поддиректории antennapatterns (это может быть директория или символическая ссылка на директорию) находится конфигурация диаграмм направленности антенн — это набор файлов, содержащий специальный служебный файл и группу файлов данных для каждого луча. Внутри этой папки должны находиться:

  • обязательный служебный файл с именем «GeoPos.in»; 

  • один или несколько файлов с расширением «.txt», содержащих данные диаграммы направленности. 

Файл GeoPos.in содержит географические координаты опорной позиции (reference position) спутника, для которого были рассчитаны эти диаграммы направленности. Файл содержит одну строку в формате: 

Latitude Longitude Altitude 

Пример:

0.0 10.0 35786000.0

Каждый из файлов лучей (Pattern Files, например, 1.txt, Beam_12.txt) описывает диаграмму направленности для одного луча. Имя файла определяется ID луча. В данном случае 1 и 12.

Именование файлов лучей

  • расширение должно быть «.txt». 

  • в имени файла (до расширения) обязательно должно содержаться число. Это число будет трактоваться как ID луча (Beam ID). 

  • программный код модуля игнорирует текстовую часть префикса, если она одинакова для всех файлов в папке. 

Пример:

beam_3.txt -> ID=3.
Spot5.txt -> ID=5.

Формат содержимого файла

Файл представляет собой сетку значений усиления антенны. Формат строки:

Latitude Longtitude [Gain_dB] 

Latitude — широта точки (в градусах);

Longtitude — долгота точки (в градусах);

Gain_dB — усиление антенны в децибелах. Это число (например, 50.5), либо специальное строковое значение. Специальное значение для отсутствия сигнала: если в какой-то точке луч не покрывает территорию, вместо числа нужно написать NaN (или nan, NaN, NAN — регистр не важен). Код преобразует это в «Not a Number», что означает недопустимую позицию.

Требования к структуре данных

  • Сортировка: должна быть четкая сетка. Сначала идут все точки для первой широты (перебирая долготы), затем для второй широты и так далее. 

  • Постоянный шаг: расстояние между соседними широтами должно быть одинаковым для всего файла. То же самое для долготы. Код вычисляет шаг по первым двум значениям и предполагает, что он неизменен. 

  • Координаты: широта от -90 до 90, долгота от -180 до 180. 

Пример файла луча (3.txt)

Представим, что у нас есть грубая сетка с шагом 10 градусов по широте и 20 по долготе для луча, ориентированного на широту 50 и долготу 10. Тогда файл луча 3 может выглядеть следующим образом:

Листинг 9.1: Пример файла луча 3.txt

40.0 0.0 35.2
40.0 20.0 36.5
40.0 40.0 35.0
50.0 0.0 48.0
50.0 20.0 52.1
50.0 40.0 47.8
60.0 0.0 NaN
60.0 20.0 36.0
60.0 40.0 35.5

Строки 1-3: Широта 40. Долготы 0, 20, 40. Усиление в интервале 35-36 дБ.

Строки 4-6: Широта 50 (центр луча). Усиление выше (48-52 дБ).

Строки 7-9: Широта 60. В точке (60, 0) стоит NaN, значит там нет покрытия.

Поддиректория beams

В поддиректории beams находятся файлы fwdConf.txt и rtnConf.txt Они выполняют назначение шлюзов по лучам. Фрагмент такого файла показан в листинге 9.2.

Листинг 9.2: Фрагмент файла rtnConf.txt

1 1 1 1
2 2 1 2
3 1 1 1
4 2 1 2
5 1 2 1
6 2 2 2
7 1 2 1
8 2 2 2
9 1 2 1
10 3 1 3
11 4 1 1
12 3 2 1

Формат строки файла:

Beam_ID User_Channel_ID Gateway_ID Feeder_Channel_ID 

Beam_ID — идентификатор спутникового луча (целое число). Обычно нумерация начинается с 1. Поскольку данные загружаются в вектор построчно, порядок строк важен: первая строка соответствует лучу с ID 1, вторая — ID 2 и так далее.

User_Channel_ID — идентификатор частотного канала для пользовательской линии (User Link) (целое число). Это индекс, определяющий, какую часть полосы пропускания пользовательской линии занимает этот луч. Должен быть в пределах от 1 до общего количества каналов пользовательской линии.

Gateway_ID — идентификатор шлюза (Gateway), к которому привязан этот луч (целое число). Определяет, какой наземный шлюз обслуживает данный луч. Если используется режим созвездия, это значение в коде может быть перезаписано алгоритмом распределения (балансировки) шлюзов, но формат файла от этого не меняется.

Feeder_Channel_ID — идентификатор частотного канала для фидерной линии (Feeder Link) (целое число). Это индекс, определяющий частоту для связи между спутником и шлюзом.

Количество строк (лучей) в файле прямой линии (fwdConf.txt) должно строго совпадать с количеством строк в файле обратной линии (rtnConf.txt). Все значения должны быть целыми положительными числами. Использование чисел с плавающей точкой (например, 1.0) приведет к ошибке чтения. Количество лучей ограничено числом 1000.

Поддиректория waveforms

В поддиректории waveforms должны находится файлы:

  • waveforms.txt 

  • default_waveform.txt 

Они определяют волновые формы, которые разрешено использовать при передаче данных и волновую форму, которая будет выбираться по умолчанию. Содержание файла gw_positions.txt показано в листинге 9.3.

Листинг 9.3: Фрагмент файла waveforms.txt

2       2       1/3     14      262
3       2       1/3     38      536
4       2       1/2     59      536
5       2       2/3     85      536
6       2       3/4     96      536
7       2       5/6     108     536
8       3       2/3     115     536
9       3       3/4     130     536

Формат строки файла:

ID ModBits CodingRate PayloadBytes DurationSymbols [PreambleSymbols] 

где

ID — идентификатор волновой формы.

ModBits — тип модуляции, возможные значения:

  • 1 — BPSK 

  • 2 — QPSK 

  • 3 — 8PSK 

  • 4 — 16QAM 

CodingRate — скорость помехоустойчивого кодирования. Поддерживаемые комбинации:

  • BPSK: 1/3 

  • QPSK: 1/3, 1/2, 2/3, 3/4, 5/6 

  • 8PSK: 2/3, 3/4, 5/6 

  • 16QAM: 3/4, 5/6 

PayloadBytes — размер полезной нагрузки (данных) в одном пакете данной волновой формы.

DurationSymbols — общая длительность пакета (burst) в символах. Обычно соответствует стандартным значениям, определенным в классе (например, 536 для короткого пакета или 1616 для длинного).

PreambleSymbols — длина преамбулы в символах. Если преамбула не нужна или равна нулю, то ее можно не указывать.

Порядок строк в файле не важен для чтения, но ID волновых форм должны быть уникальным.

Файл default_waveform.txt должен содержать одно число — ID волновой формы которая будет применяться по умолчанию.

Поддиректория beamhopping

В поддиректории beamhopping размещается статический план переключения лучей ( BSTP), один или несколько файлов. Если папка есть, SimulationHelper подключает прямой линк beam hopping и по умолчанию указывает файл beamhopping/SatBstpConf_GW1.txt (имя можно сменить атрибутом StaticBeamHoppingConfigFileName в ns3::SatBstpController). Каждая строка файла — набор целых беззнаковых чисел, разделённых запятой (пробелы после запятой допустимы). Первый столбец — длительность действия этой строки плана, в количестве суперкадров DVB-S2X. Остальные столбцы — идентификаторы включённых в этот интервал времени лучей (beam id). Лучи, не перечисленные в строке, для этого временного окна выключаются. Строки читаются по порядку, после последней снова берётся первая (циклический паттерн). Пример файла показан в листинге 9.4.

Листинг 9.4: Фрагмент файла SatBstpConf_GW1.txt

3, 1, 4, 12, 28
1, 2, 13, 25, 40
2, 11, 3, 26, 41
1, 1, 14, 12, 27

первая строка: в течении 3 суперкадров держатся включёнными лучи 1, 4, 12, 28; остальные зарегистрированные лучи этого GW в это время выключены. Требования к файлу:

  • в одной строке нельзя дважды указать один и тот же beam Id

  • для одного GW в одной строке нельзя одновременно включить два луча с одинаковым feeder frequency id

  • каждый включённый в симуляции луч должен хотя бы раз встретиться в какой-то строке BSTP

Поддиректория standard

В директории standard находится файл-конфиг: standard.txt. Его назначение — выбрать глобальный стандарт сценария, от которого дальше зависит, какие классы/устройства и ветки инициализации будут использованы (DVB или LoRa). Парсер читает из этого файла первое слово. Допустимые значения:

  • DVB 

  • LORA 

Если значение другое — произойдет ошибка (NS_FATAL_ERROR).

Поддиректория positions

В поддиректории positions размещены описания положений устройств на сцене. Это должны быть следующие файлы:

  • gw_positions.txt — файл координат шлюзов; 

  • sat_positions.txt или tles.txt - файл координат спутников; 

  • ut_positions.txt - файл координат пользовательских терминалов. 

Содержание файла gw_positions.txt показано в листинге 9.5.

Листинг 9.5: Фрагмент файла gw_positions.txt

44.50 13.50 20000.0
37.25 23.75 20000.0
44.50 13.50 20000.0
37.25 23.75 20000.0

Формат строки файла:

Latitude Longtitude Height 

Latitude - географическая широта в градусах. Диапазон от -90.0 до 90.0.

Longtitude - географическая долгота в градусах. Диапазон от -180.0 до 180.0.

Height - высота над уровнем моря в метрах. Для спутников это будет,например, 35786000, для шлюзов и UT высота местности.

По высоте и координатам в примере мы можем понять, что показаны координаты шлюзов расположенных на борту двух HAP. Порядок строк в файле критически важен для сопоставления с ID объектов: 1-я строка соответствует объекту с ID 1, 2-я строка соответствует объекту с ID 2 и т.д.

Файл sat_positions.txt обычно используется для одного геостационарного спутника (или статичных спутников в тестах). Код ожидает, что в векторе будет только одна позиция, поэтому в файле должна быть одна строка.

Количество строк

  • gw_positions.txt

количество строк должно совпадать с количеством уникальных Gateway_ID, используемых в конфигурации лучей.

  • sat_positions.txt

обычно состоит из нескольких строк (по числу спутников). Если используется динамическое созвездие, то вместо этого файла используется файл с именем tles.txt. Он содержит TLE-данными спутников созвездия. В листинге 9.6  показан фрагмент такого файла для созвездия «Койпер», состоящего из 1156 аппаратов.

Листинг 9.6: Фрагмент файла tles.txt

1156
Kuiper-630 0
1 00001U 00000ABC 00001.00000000  .00000000  00000-0  00000+0 0    04
2 00001  51.9000   0.0000 0000001   0.0000   0.0000 14.80000000    02
Kuiper-630 1
1 00002U 00000ABC 00001.00000000  .00000000  00000-0  00000+0 0    05
2 00002  51.9000   0.0000 0000001   0.0000  10.5882 14.80000000    07
Kuiper-630 2
1 00003U 00000ABC 00001.00000000  .00000000  00000-0  00000+0 0    06
2 00003  51.9000   0.0000 0000001   0.0000  21.1765 14.80000000    06
  • ut_positions.txt

количество строк должно быть равно количеству создаваемых UT (или больше, если вы используете только часть списка).  В текущей реализации модуля Satellite существуют трудности с использованием сцен, чьи файлы расположены вне директории модуля. А именно, не работает механизм настройки путей к директориям таких сцен. Чтобы преодолеть этот недостаток, будем в директории data/scenario модуля Satellite создавать символические ссылки на наши сцены и модуль будет работать с ними как со своими собственными.

9.3 Назначение частот

В модуле Satellite частоты и полосы каналов задаются в два этапа:

  1. Задание плана частот по лучам, выполняется в файлах сцены beams/fwdConf.txt и beams/rtnConf.txt Там для каждого луча указываются U_FREQ_ID и F_FREQ_ID (ID пользовательской и фидерной частоты). 

  2. Физические значения (центральная частота, ширины полос, число каналов, roll-off) — через атрибуты ns3::SatConf, используются следующие атрибуты (они фактически задают сетку каналов): 

    • FwdFeederLinkBandwidth 

    • FwdFeederLinkBaseFrequency 

    • RtnFeederLinkBandwidth 

    • RtnFeederLinkBaseFrequency 

    • FwdUserLinkBandwidth 

    • FwdUserLinkBaseFrequency 

    • RtnUserLinkBandwidth 

    • RtnUserLinkBaseFrequency 

    • FwdUserLinkChannels 

    • RtnUserLinkChannels 

    • FwdFeederLinkChannels 

    • RtnFeederLinkChannels 

Соответствие ID канала и его центральной частоты устанавливается следующим образом. Эти атрибуты задают общую «шкалу»:

  • базовую частота назначенного диапазона (*BaseFrequency

  • ширину диапазона (*Bandwidth

  • число каналов (*Channels

Для определения параметров конкретного канала freqId подставляется в формулу:

channelBw = LinkBandwidth / LinkChannels

baseForId = BaseFrequency + (freqId — 1) * channelBw

т.е.:

  • U_FREQ_ID=1 → первый частотный слот; 

  • U_FREQ_ID=2 → второй слот. 

и т.д.

9.4 Назначение IP-адресов

IP-адреса в модуле Satellite по умолчанию назначаются автоматически через Ipv4AddressHelper внутри SatUserHelper. Вручную это можно сделать функциями:

  • SatUserHelper::SetUtBaseAddress(...) 

  • SatUserHelper::SetGwBaseAddress(...) 

  • SatUserHelper::SetBeamBaseAddress(...) 

Данные функции назначают базовые адреса, но полностью «ручное» (произвольное, per-node/per-interface) назначение IP в Satellite без правки кода модуля — штатно не предусмотрено, так как потребуется править логику маршрутов/ARP/handover.

9.5 Настройка маршрутизации

Базовая маршрутизация Satellite настраивается хелперами автоматически, для маршрута «произвольный источник -> произвольный приемник» вам нужно задать статические маршруты обычными средствами NS-3 API. Как это делается по шагам:

Шаг 1. Создать сценарий через SimulationHelper/SatHelper

После CreateSatScenario() в Satellite уже будут:

  • IP на интерфейсах (Assign); 

  • маршруты по умолчанию у UT/GW пользователей; 

  • маршруты между GW и подсетями UT в луче (PopulateBeamRoutings). 

Шаг 2. Найти узлы и адрес назначения

Берем нужные Ptr и IP-адрес назначения (конечный хост или подсеть).

Шаг 3. Добавить маршрут на промежуточных узлах

Через Ipv4StaticRoutingHelper:

  • SetDefaultRoute(...) — маршрут по умолчанию; 

  • AddNetworkRouteTo(...) — маршрут к конкретной сети; 

  • при необходимости AddHostRouteTo(...) — к конкретному хосту. 

Листинг 9.7 демонстрирует этот подход.

Листинг 9.7: Задание маршрута средствами API NS-3

Ipv4StaticRoutingHelper rh;

// Source node.
Ptr<Ipv4> ipv4Src = srcNode->GetObject<Ipv4>();

Ptr<Ipv4StaticRouting> srSrc = rh.GetStaticRouting(ipv4Src);
srSrc->SetDefaultRoute(nextHopFromSrc, outIfSrc);

// Intermediate node.
Ptr<Ipv4> ipv4Mid = midNode->GetObject<Ipv4>();
Ptr<Ipv4StaticRouting> srMid = rh.GetStaticRouting(ipv4Mid);
srMid->AddNetworkRouteTo(Ipv4Address(«10.10.2.0»),
Ipv4Mask(«255.255.255.0»),
nextHopFromMid,
outIfMid);

// Destination side router (if you need backward route).
Ptr<Ipv4> ipv4DstR = dstRouter->GetObject<Ipv4>();
Ptr<Ipv4StaticRouting> srDstR = rh.GetStaticRouting(ipv4DstR);
srDstR->AddNetworkRouteTo(Ipv4Address(«10.10.1.0»),
Ipv4Mask(«255.255.255.0»),
nextHopToSrcNet,
outIfDstR);

Можно ли менять маршрут динамически во время симуляции? Да, возможны следующие варианты.

Вариант А (штатный для хендовера в Satellite)

В модуле уже есть методы динамического обновления маршрутов:

  • SatUserHelper::UpdateUtRoutes(...) 

  • SatUserHelper::UpdateGwRoutes(...) 

Они вызываются колбеками при хендовере. Листинг 9.8 демонстрирует «ручное» использование этих функций для смены маршрута.

Листинг 9.8: Динамическое задание маршрута средствами модуля Sattelite

// After simulationHelper->CreateSatScenario(...);
Ptr<SatUserHelper> userHelper = simulationHelper->GetSatelliteHelper()->GetUserHelper();

// MAC of satellite interface of UT (SatNetDevice on utNode)
Ptr<NetDevice> utSatNd = /* ... get SatNetDevice pointer from UT object ... */;
Address utMac = utSatNd->GetAddress();

// MAC of satellite interface of GW (old and new)
Address oldGwMac = Mac48Address(«aa:bb:cc:dd:ee:ff»); // get from gwNode
Address newGwMac = Mac48Address(«11:22:33:44:55:66»);

// Like for intra-/inter-GW handover on side of  GW/router
userHelper->UpdateGwRoutes(utMac, oldGwMac, newGwMac);

// Like in default route and ARP change on UT to new GW
userHelper->UpdateUtRoutes(utMac, newGwMac);

Вариант Б (ваша собственная динамическая policy)

Можно в любой момент, с помощью Simulator::Schedule(…), запланировать по времени вызов колбека, а внутри него:

  • удалить старый маршрут (маршруты); 

  • добавить новые маршруты через Ipv4StaticRouting(...)

  • при L2-смене next-hop при необходимости обновить ARP

Листинг 9.9 демонстрирует этот подход.

Листинг 9.9: Динамическое задание маршрута средствами API NS-3

// Let's define collback.
void ReRoute(Ptr<Node> n, Ipv4Address newGw, uint32_t ifIndex)
{
Ipv4StaticRoutingHelper rh;
Ptr<Ipv4StaticRouting> rt = rh.GetStaticRouting(n->GetObject<Ipv4>());

// Example: remove old route and set new default.
rt->RemoveRoute(rt->GetNRoutes() — 1);
rt->SetDefaultRoute(newGw, ifIndex);
}

// Schedule calback call after 30 seconds.

Simulator::Schedule(Seconds(30.0), &ReRoute, utNode, Ipv4Address(«40.1.2.1»), satIfIndex);

9.6 Разбор сценария sat-cbr-example

Рассмотрим один из основных тестов с названием sat-cbr-example. Цель этого сценария — смоделировать обмен пакетами данных через геостационарный спутник между пользователями, подключенными к шлюзу (Gateway, GW) и пользователями, подключенными к пользовательским терминалам (UT). Симуляция настраивается через аргументы командной строки, что позволяет легко менять:

  • размер пакетов; 

  • интервал между отправкой пакетов; 

  • масштаб сцены (simple, larger, full). 

Сценарий демонстрирует два способа создания трафика:

  • ручная настройка (для сцены full): Создание и настройка каждого приложения (отправителя и получателя) индивидуально; 

  • настройка через хелпер (для сцен simple и larger): Использование высокоуровневой функции-помощника для быстрого добавления трафика. 

9.6.1 Инициализация параметров

Установка значений по умолчанию

В этом блоке кода объявляются переменные, которые определяют параметры симуляции. Им присваиваются значения по умолчанию:

#include «ns3/...» // Include all required ns3 modules

...

NS_LOG_COMPONENT_DEFINE(«sat-cbr-example»); // Define logging component

int main(int argc, char* argv[])
{
    // 1.1. Set default parameter values
    uint32_t beamIdInFullScenario = 10; // Beam ID for «full» scenario
    uint32_t packetSize = 512;          // Packet size in bytes
    std::string interval = «1s»;        // Packet transmission interval
    std::string scenario = «simple»;    // Default scenario type
    SatHelper::PreDefinedScenario_t satScenario = SatHelper::SIMPLE;

Далее делается настройка конфигурации теста:

    // 1.2. Global simulation configuration
    Config::SetDefault(«ns3::SatEnvVariables::EnableSimulationOutputOverwrite», BooleanValue(true));
    Config::SetDefault(«ns3::SatHelper::PacketTraceEnabled», BooleanValue(true));
    Ptr<SimulationHelper> simulationHelper = CreateObject<SimulationHelper>("example-cbr");
  • EnableSimulationOutputOverwrite: Разрешает перезаписывать файлы с результатами предыдущих запусков; 

  • PacketTraceEnabled: Включает детальное отслеживание (трассировку) всех пакетов в симуляции. Результаты будут сохранены в файлы трассировки (.tr), что позволяет анализировать задержки, потери и другие метрики; 

  • SimulationHelper: Создается объект-помощник, который значительно упрощает процесс настройки и запуска спутниковых симуляций. Здесь «example-cbr» — это тег, который будет использован для создания папки с результатами симуляции. 

Чтение аргументов командной строки

Данный блок исходного кода позволяет «превращать» глобальные переменные теста в аргументы командной строки. После такой процедуры пользователь получает возможность при запуске менять значения глобальных переменных теста, это избавляет от перекомпиляции кода и таким образом экономит значительное время если исследования требуют многократных запусков сценария с разными значениями параметров. Например в третьей строке, показанного ниже кода, создается аргумент командной строки с именем «packetSize», который внутри сценария будет связан с переменной packetSize. Также добавляется краткое текстовое описание аргумента.

    CommandLine cmd;

    cmd.AddValue(«beamIdInFullScenario», «The beam ID to use in the 'full' scenario», beamIdInFullScenario);
    cmd.AddValue(«packetSize», «Size of CBR packets in bytes», packetSize);
    cmd.AddValue(«interval», «Time interval between CBR packets», interval);
    cmd.AddValue(«scenario», «Scenario type ('simple' or 'full')», scenario);
    simulationHelper->AddDefaultUiArguments(cmd); // Adds default UI arguments (simulation time, etc.)

    cmd.Parse(argc, argv); // Parses command-line arguments  

Например, чтобы запустить сценарий с новыми значениями размера пакета, интервала между пакетами и на полной сцене можно использовать такую команду:

$ ./ns3 r «sat-cbr-example --packetSize=1024 --interval=0.5s --scenario=full» 

Чтобы получить список доступных аргументов командной строки сценария, нужно передать ему опцию «help»:

$ ./ns3 run «sat-cbr-example --help» 

Результатом будет такой вывод в консоль:

 [Program Options] [General Arguments]

Program Options:

    --beamIdInFullScenario:  Id where Sending/Receiving UT is selected in FULL scenario. (used only when scenario is full)  [10]

    --packetSize:            Size of constant packet (bytes) [512]

    --interval:              Interval to sent packets in seconds, (e.g. (1s) [1s]

    --scenario:              Test scenario to use. (simple, larger or full [simple]

    --OutputPath:            Output path for storing the simulation statistics

General Arguments:

    --PrintGlobals:              Print the list of globals.

    --PrintGroups:               Print the list of groups.

    --PrintGroup=[group]:        Print all TypeIds of group.

    --PrintTypeIds:              Print all TypeIds.

    --PrintAttributes=[typeid]:  Print all attributes of typeid.

    --PrintVersion:              Print the ns-3 version.

    --PrintHelp:                 Print this help message. 

Выбор и подготовка сцены

if (scenario == «larger») { satScenario = SatHelper::LARGER; }

else if (scenario == «full») { satScenario = SatHelper::FULL; }

simulationHelper->SetOutputTag(scenario);      // Tag for output files

simulationHelper->SetSimulationTime(Seconds(11)); // Total simulation time — 11 seconds

simulationHelper->SetBeams(beamsEnabled.str());  // Enables only specified beam (for «full» scene)
  • Строковое значение scenario преобразуется в соответствующий элемент перечисления satScenario, чтобы указать объекту SatHelper какой вариант сцены использовать при моделировании; 

  • Устанавливается текстовый префикс, который будет использован для имен файлов с результатами симуляции; 

  • Устанавливается время работы симуляции (11 секунд); 

  • Для сцены full, указывается, какой именно луч спутника нужно использовать. 

9.6.2 Создание топологии сети

Топология сети в этом тесте задается сценой с названием «geo-33E». Сцены модуля хранятся в папке ~/workspace_ns3.43/ns-3.43/contrib/satellite/data/scenarios. Загрузка сцены выполняется следующими строчками кода:

    simulationHelper->LoadScenario(«geo-33E»); // Loads satellite configuration

    Ptr<SatHelper> helper = simulationHelper->CreateSatScenario(satScenario); // Creates satellite scenario
  • LoadScenario(«geo-33E»): Загружает сцену эксперимента соответствующую указанному в аргументе спутнику, в данном случае для geo-33E ( геостационарный спутник, расположенный на 33-м градусе восточной долготы) информацию о лучах, мощности, частотах и т.д. 

  • CreateSatScenario(satScenario): Функция создает всю сетевую инфраструктуру в соответствии с выбранной сценой: 

    • SIMPLE: Один шлюз (GW), один спутник (SAT), несколько пользовательских терминалов (UT); 

    • LARGER: Более сложная топология с большим количеством узлов; 

    • FULL: Самая сложная и реалистичная топология, имитирующая реальное покрытие спутника с множеством лучей. 

После этого шага у нас есть готовая к работе модель сети.

9.6.3 Создание и настройка трафика

Здесь логика разделяется на две ветки в зависимости от сцены.

Сцена 1: if (scenario == «full») — выполняется ручная настройка 

Этот метод позволяет наиболее гибко управлять трафиком. В блоке кода ниже выполняется разделение узлов на группы:

    // 5.1. Get required nodes
    NodeContainer uts = helper->GetBeamHelper()->GetUtNodes(0, beamIdInFullScenario);
    NodeContainer utUsers = Singleton<SatTopology>::Get()->GetUtUserNodes(uts.Get(0));
    NodeContainer gwUsers = Singleton<SatTopology>::Get()->GetGwUserNodes();
  • GetUtNodes(): Находит все пользовательские терминалы (UT) в указанном луче (beamIdInFullScenario); 

  • GetUtUserNodes(): Находит конечных пользователей (например, компьютеры), подключенные к первому найденному UT; 

  • GetGwUserNodes(): Находит конечных пользователей, подключенных к шлюзу (GW). 

Далее создается трафик от шлюза к пользовательским терминалам:

    // 5.2. Create traffic from GW to UT (Forward Link)
    PacketSinkHelper sinkHelper(«ns3::UdpSocketFactory», InetSocketAddress(helper->GetUserAddress(gwUsers.Get(0)), port));
    CbrHelper cbrHelper(«ns3::UdpSocketFactory», InetSocketAddress(helper->GetUserAddress(utUsers.Get(0)), port));

    // ... setting attributes (packet size, interval) ...
    ApplicationContainer gwSink = sinkHelper.Install(gwUsers.Get(0)); // Install «receiver» on GW user
    ApplicationContainer gwCbr = cbrHelper.Install(gwUsers.Get(0));   // Install «sender» on GW user

    // ... configuring operation time (sending from 1.0s to 2.1s) ...
  • Создается приложение-приемник (PacketSink) на стороне пользователя GW

  • Создается приложение-отправитель (CbrApplication) на стороне пользователя GW. Оно будет отправлять UDP-пакеты пользователю UT

  • Отправка начинается на 1-й секунде и заканчивается на 2.1-й. 

    // 5.3. Create traffic from UT to GW (Return Link)
    sinkHelper.SetAttribute(«Local», ...); // Reconfigure «receiver» for UT side
    cbrHelper.SetAttribute(«Remote», ...); // Reconfigure «sender» for UT side
    ApplicationContainer utSink = sinkHelper.Install(utUsers.Get(0)); // Install «receiver» on UT user
    ApplicationContainer utCbr = cbrHelper.Install(utUsers.Get(0));   // Install «sender» on UT user

    // ... configuring operation time (sending from 7.0s to 9.1s) ...
  • Аналогично создается пара «отправитель-получатель», но уже в обратную сторону: от пользователя UT к пользователю GW

  • Эта сессия начинается позже, на 7-й секунде. 

Сцена 2: else (для simple и larger) 

Настройка через хелпер. Этот метод проще, но менее гибкий. Он применяет одинаковые правила для всех узлов.

    // simulationHelper->GetTrafficHelper()->AddCbrTraffic(SatTrafficHelper::FWD_LINK, ...); // Commented code for Forward Link
    simulationHelper->GetTrafficHelper()->AddCbrTraffic(
    SatTrafficHelper::RTN_LINK, // Create traffic on RETURN link (UT -> GW)
    SatTrafficHelper::UDP,      // UDP protocol
    Time(interval), packetSize, // Parameters from command line
    Singleton<SatTopology>::Get()->GetGwUserNodes(), // Receivers (GW users)
    Singleton<SatTopology>::Get()->GetUtUserNodes(), // Senders (UT users)
    Seconds(7.0), Seconds(9.1), Seconds(0)); // Operation time (start, stop, delay)  
  • AddCbrTraffic(): высокоуровневая функция, которая автоматически создает приложения CBR для всех пар «отправительполучитель».В данном примере она создает трафик только на обратном канале (Return Link) от всех пользователей UT ко всем пользователям GW

  • Время работы (с 7.0 с по 9.1 с) совпадает со временем ручной настройки для этого направления. 

9.6.4 Запуск симуляции

Запуск симуляции выполняется в следующих строках:

    NS_LOG_INFO(«--- sat-cbr-example ---»); // Output summary information to console
    NS_LOG_INFO(«  Scenario used: « << scenario);

    // ...

    simulationHelper->RunSimulation(); // LAUNCH simulation!
    return 0;
}
  • NS_LOG_INFO: выводит в консоль итоговые параметры симуляции, чтобы пользователь мог убедиться, что все настроено правильно. RunSimulation() — это финальный вызов, который запускает движок NS-3

  • Симуляция работает 11 секунд (как было задано), генерирует события (отправку пакетов), обрабатывает их и записывает результаты в файлы трассировки. 

9.7 Результаты симуляции

Запустим рассмотренный в разделе 9.6 сценарий:

$ ./ns3 run «sat-cbr-example --packetSize=1024 --interval=0.5s --scenario=full» 

Во время симуляции результаты сохраняются в папку:

~/workspace_ns3.43/ns-3.43/contrib/satellite/data/sims

В этом каталоге отыскиваем директорию с именем «example-cbr» (такое имя тега было передано конструктору объекта simulationHelper). В результатах появится папка «full». Дерево директории с результатами будет иметь следующий вид:

example-cbr
+-- full
|    +-- PacketTrace.log

Папка будет содержать единственный файл PacketTrace.log с трассировкой пакетов. Размер файла 18 Мегабайт. Начало этого файла представлено в листинге 9.10:

Листинг 9.10: PacketTrace.log для конфигурации «full»

COLUMN DESCRIPTIONS
-------------------
Time
Packet event (SND, RCV, DRP, ENQ)
Node type (UT, SAT, GW, NCC, TER)
Node id
MAC address
Log level (ND, LLC, MAC, PHY, CH)
Link direction (FWD, RTN)
Packet info (List of: Packet id, source MAC address, destination MAC address)
-------------------

0.05 SND GW 1 00:00:00:00:00:0e ND FWD 0 
0.05 ENQ GW 1 00:00:00:00:00:0e LLC FWD 0 00:00:00:00:00:0e ff:ff:ff:ff:ff:ff 
0.05 SND GW 1 00:00:00:00:00:1e ND FWD 1 
0.05 ENQ GW 1 00:00:00:00:00:1e LLC FWD 1 00:00:00:00:00:1e ff:ff:ff:ff:ff:ff 
0.05 SND GW 1 00:00:00:00:00:2e ND FWD 2 
0.05 ENQ GW 1 00:00:00:00:00:2e LLC FWD 2 00:00:00:00:00:2e ff:ff:ff:ff:ff:ff 
0.05 SND GW 1 00:00:00:00:00:3e ND FWD 3 
0.05 ENQ GW 1 00:00:00:00:00:3e LLC FWD 3 00:00:00:00:00:3e ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:00:4e ND FWD 4 
0.05 ENQ GW 2 00:00:00:00:00:4e LLC FWD 4 00:00:00:00:00:4e ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:00:5e ND FWD 5 
0.05 ENQ GW 2 00:00:00:00:00:5e LLC FWD 5 00:00:00:00:00:5e ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:00:6e ND FWD 6 
0.05 ENQ GW 2 00:00:00:00:00:6e LLC FWD 6 00:00:00:00:00:6e ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:00:7e ND FWD 7 
0.05 ENQ GW 2 00:00:00:00:00:7e LLC FWD 7 00:00:00:00:00:7e ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:00:8e ND FWD 8 
0.05 ENQ GW 2 00:00:00:00:00:8e LLC FWD 8 00:00:00:00:00:8e ff:ff:ff:ff:ff:ff 
0.05 SND GW 3 00:00:01:00:00:9e ND FWD 9 
0.05 ENQ GW 3 00:00:00:00:00:9e LLC FWD 9 00:00:00:00:00:9e ff:ff:ff:ff:ff:ff 
0.05 SND GW 1 00:00:00:00:00:ae ND FWD 10 
0.05 ENQ GW 1 00:00:00:00:00:ae LLC FWD 10 00:00:00:00:00:ae ff:ff:ff:ff:ff:ff 
0.05 SND GW 1 00:00:00:00:00:be ND FWD 11 
0.05 ENQ GW 1 00:00:00:00:00:be LLC FWD 11 00:00:00:00:00:be ff:ff:ff:ff:ff:ff 
0.05 SND GW 1 00:00:00:00:00:ce ND FWD 12 
0.05 ENQ GW 1 00:00:00:00:00:ce LLC FWD 12 00:00:00:00:00:ce ff:ff:ff:ff:ff:ff 
0.05 SND GW 1 00:00:00:00:00:de ND FWD 13 
0.05 ENQ GW 1 00:00:00:00:00:de LLC FWD 13 00:00:00:00:00:de ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:00:ee ND FWD 14 
0.05 ENQ GW 2 00:00:00:00:00:ee LLC FWD 14 00:00:00:00:00:ee ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:00:fe ND FWD 15 
0.05 ENQ GW 2 00:00:00:00:00:fe LLC FWD 15 00:00:00:00:00:fe ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:01:0e ND FWD 16 
0.05 ENQ GW 2 00:00:00:00:01:0e LLC FWD 16 00:00:00:00:01:0e ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:01:1e ND FWD 17 
0.05 ENQ GW 2 00:00:00:00:01:1e LLC FWD 17 00:00:00:00:01:1e ff:ff:ff:ff:ff:ff 
0.05 SND GW 2 00:00:00:00:01:2e ND FWD 18 
0.05 ENQ GW 2 00:00:00:00:01:2e LLC FWD 18 00:00:00:00:01:2e ff:ff:ff:ff:ff:ff 

Этот фрагмент лога показывает начальный этап работы симуляции, а не основной пользовательский трафик CBR, который мы настраивали в коде (он должен начаться в 1.0 секунду). Трафик, который мы здесь видим, — это служебный или управляющий трафик. Судя по широковещательному MAC-адресу назначения (ff:ff:ff:ff:ff:ff), это, скорее всего, процесс обнаружения устройств в сети, аналогичный протоколу ARP (Address Resolution Protocol), или рассылка какой-то начальной управляющей информации от шлюзов ко всем остальным узлам сети.  Разберем одну конкретную строку, чтобы понять каждую колонку:

0.0500152 SND GW 1 00:00:00:00:00:0e MAC FWD 0 00:00:00:00:00:0e ff:ff:ff:ff:ff:ff

«0.0500152»: Время в секундах с момента начала симуляции, когда произошло это событие. Высокая точность показывает, что это не тот же момент, что и 0.05, а на 15.2 мкс позже. «SND»: Тип события. Возможные типы событий:

  • SND (Send): Пакет «отправляется» с одного уровня сетевого стека на другой. 

  • ENQ (Enqueue): Пакет ставится в очередь на отправку. 

  • RCV (Receive): Пакет получен. 

  • DRP (Drop): Пакет был отброшен (например, из-за переполнения очереди). 

«GW»: Тип узла, сгенерировавшего событие. Здесь GW — это шлюз (Gateway). «1»: Идентификатор узла ( Node id). В этой симуляции, как минимум, 5 шлюзов (с ID 1 по 5).

«00:00:00:00:00:0e»: MAC-адрес сетевого интерфейса узла, на котором происходит событие.

«MAC»: Уровень сетевого стека (Log level), на котором произошло событие. Возможные уровни:

  • ND (Network Device): Самый верхний уровень моделируемого спутникового устройства. Здесь создается пакет. 

  • LLC (Logical Link Control): Уровень управления логическим каналом. 

  • MAC (Media Access Control): Уровень, отвечающий за доступ к среде передачи и MAC-адресацию. 

  • PHY (Physical): Физический уровень, который преобразует цифровые данные в радиосигнал. 

«FWD»: Направление передачи(Link direction):

  • FWD (Forward Link): Прямой канал (Шлюз -> Спутник -> Пользовательский терминал). 

  • RTN (Return Link): Обратный канал (Пользовательский терминал -> Спутник -> Шлюз). 

«0 00:00:00:00:00:0e ff:ff:ff:ff:ff:ff»: Информация о пакете(Packet info).

  • 0: Уникальный ID пакета в рамках симуляции. 

  • 00:00:00:00:00:0e: MAC-адрес источника. 

  • ff:ff:ff:ff:ff:ff: MAC-адрес назначения. В данном случае это широковещательный адрес, означающий «пакет предназначен всем». 

9.7.1 Что происходит в логе 

Если проследить за жизнью одного пакета (например, с ID 0), мы увидим следующую последовательность:

Шаг 1: Создание и постановка в очередь (время 0.05)

0.05 SND GW 1 00:00:00:00:00:0e ND FWD 0
0.05 ENQ GW 1 00:00:00:00:00:0e LLC FWD 0 00:00:00:00:00:0e ff:ff:ff:ff:ff:ff
0.05 SND GW 1 00:00:00:00:00:1e ND FWD 1
0.05 ENQ GW 1 00:00:00:00:00:1e LLC FWD 1 00:00:00:00:00:1e ff:ff:ff:ff:ff:ff
  1. В момент времени 0.05 на шлюзе с ID 1 на уровне ND создается пакет с ID 0. Это его «рождение».

    0.05 SND GW 1 ... ND FWD 0
    
  2. Сразу же после создания этот пакет ставится в очередь на уровне LLC. Оба события происходят в один и тот же момент симуляционного времени, так как обработка внутри узла считается мгновенной.

    0.05 ENQ GW 1 ... LLC FWD 0 ...
    

Этот процесс (SND -> ENQ) повторяется для множества пакетов (с ID 0 по 71) и на всех шлюзах (GW 1, 2, 3, 4, 5).

Шаг 2: Обработка и спуск вниз по стеку протоколов (время 0.0500152с)

0.0500152 SND GW 1 00:00:00:00:00:0e LLC FWD 0 00:00:00:00:00:0e ff:ff:ff:ff:ff:ff
0.0500152 SND GW 1 00:00:00:00:00:0e MAC FWD 0 00:00:00:00:00:0e ff:ff:ff:ff:ff:ff
0.0500152 SND GW 1 00:00:00:00:00:0e PHY FWD 0 00:00:00:00:00:0e ff:ff:ff:ff:ff:ff
0.0500152 SND GW 1 00:00:00:00:00:1e LLC FWD 1 00:00:00:00:00:1e ff:ff:ff:ff:ff:ff
0.0500152 SND GW 1 00:00:00:00:00:1e MAC FWD 1 00:00:00:00:00:1e ff:ff:ff:ff:ff:ff
0.0500152 SND GW 1 00:00:00:00:00:1e PHY FWD 1 00:00:00:00:00:1e ff:ff:ff:ff:ff:ff

Проходит промежуток времени (0.0000152 с), который симулирует задержку на обработку внутри узла. Теперь пакет начинает свое путешествие вниз по сетевому стеку:

  1. Пакет извлекается из очереди на уровне LLC и «отправляется» на нижестоящий уровень — MAC.

    0.0500152 SND GW 1 ... LLC FWD 0 ...
    
  2. Пакет передан на уровень MAC.

    0.0500152 SND GW 1 ... MAC FWD 0 ...
    
  3. Пакет достигает физического уровня (PHY). Теперь он готов к передаче через спутниковый канал. Аналогичным образом можно разобрать оставшуюся часть лога.Чтобы увидеть трафик пользователей, нужно искать записи в логе, которые расположены после 1 секунды. В них адрес назначения уже не будет широковещательным, а будет соответствовать MAC-адресу конкретного пользователя UT.

    0.0500152 SND GW 1 ... PHY FWD 0 ...
    

Выполним симуляцию для конфигурации «simple»:

$ ./ns3 run «sat-cbr-example --packetSize=1024 --interval=0.5s --scenario=simple»

В директории результатов добавится папка с именем «simple», содержащая знакомый нам файл PacketTrace.log размером 180 килобайт (он меньше в 100 раз чем в предыдущем случае, по причине того, что симулируется только трафик от пользователей терминалов к шлюзам) и набор текстовых файлов с статистикой. Директория результатов приобрела вид:

example-cbr
+-- full
|   +-- PacketTrace.log
+-- simple
    +-- PacketTrace.log
    +-- stat-global-rtn-app-throughput-scalar.txt
    +-- stat-global-rtn-app-throughput-scatter-0.txt
    +-- stat-global-rtn-feeder-mac-throughput-scalar.txt
    +-- stat-global-rtn-feeder-mac-throughput-scatter-0.txt
    +-- stat-global-rtn-user-mac-throughput-scalar.txt
    +-- stat-global-rtn-user-mac-throughput-scatter-0.txt
    +-- stat-per-gw-rtn-app-throughput-scalar.txt
    +-- stat-per-gw-rtn-app-throughput-scatter-2.txt
    +-- stat-per-gw-rtn-feeder-mac-throughput-scalar.txt
    +-- stat-per-gw-rtn-feeder-mac-throughput-scatter-2.txt
    +-- stat-per-gw-rtn-user-mac-throughput-scalar.txt
    +-- stat-per-gw-rtn-user-mac-throughput-scatter-2.txt
    +-- stat-per-ut-rtn-app-throughput-scalar.txt
    +-- stat-per-ut-rtn-app-throughput-scatter-1.txt
    +-- stat-per-ut-rtn-feeder-mac-throughput-scalar.txt
    +-- stat-per-ut-rtn-feeder-mac-throughput-scatter-1.txt
    +-- stat-per-ut-rtn-user-mac-throughput-scalar.txt
    +-- stat-per-ut-rtn-user-mac-throughput-scatter-1.txt

Эти файлы генерируются автоматически в конце симуляции механизмом сбора статистики ns3-satellite. Когда вы создаете топологию с помощью SatHelper или SimulationHelper, в фоновом режиме «подключаются» специальные «измерительные зонды» (probes) или колбэки (callbacks) к следующим точкам сети:

  • На уровне приложений (app). 

  • На MAC-уровне со стороны шлюза (feeder-mac). 

  • На MAC-уровне со стороны пользовательского терминала (user-mac). 

Эти зонды отслеживают все проходящие пакеты, считают их объем и фиксируют время. По завершении симуляции собранные данные обрабатываются и сохраняются в текстовые файлы в удобном для анализа формате. Что в этих файлах? (разбор по структуре имени)

Имена файлов систематизированы. Давайте разберем их на примере:  stat-per-ut-rtn-user-mac-throughput-scatter-1.txt

  1. stat-...: Префикс, означающий, что это файл статистики. 

  2. Уровень агрегации (Scope): 

    • global: Статистика по всей симуляции в целом. Все данные со всех узлов суммируются или усредняются. 

    • per-gw: Статистика агрегируется по каждому шлюзу (GW) отдельно. Для каждого GW будет создан свой файл. 

    • per-ut: Статистика агрегируется по каждому пользовательскому терминалу (UT) отдельно. Для каждого UT будет создан свой файл. 

  3. Направление канала (Link Direction): 

    • rtn: обратный канал. Это трафик, идущий от UT к GW

    • fwd: прямой канал. Это трафик, идущий от GW к UT (в нашем примере только rtn, так как в коде был создан только такой трафик). 

  4. Точка измерения (Measurement Point): 

    • app: Application Layer (уровень приложения). Измеряется полезная пропускная способность, которую «видят» сами приложения (например, CbrApplication и PacketSink). Это самая точная оценка end-to-end производительности для пользователя. 

    • user-mac: User MAC Layer (MAC-уровень со стороны пользователя). Измеряется пропускная способность на физическом входе/выходе пользовательского терминала. Это «сырая» скорость, включающая служебные заголовки MAC-уровня, но без учета overhead физического уровня. 

    • feeder-mac: Feeder MAC Layer (MAC-уровень со стороны шлюза). Измеряется пропускная способность на физическом входе/выходе шлюза. 

  5. Метрика (Metric): 

    • throughput: Пропускная способность. Обычно измеряется в битах в секунду (bps). 

  6. Формат файла (File Format): 

    • -scatter: Файл для построения диаграммы рассеяния ( scatter plot). Содержит два столбца: время и значение метрики в этот момент времени. По которым можно построить график зависимости пропускной способности от времени. Пример такого файла показан ниже.

% output_type: 'OUTPUT_TYPE_SUM'
% count: 3
% sum: 24.576

% time_sec throughput_kbps
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 8.192
9 16.384
10 0
  • -scalar: Файл со скалярными значениями. Содержит итоговые, агрегированные статистики за всю симуляцию: среднее значение (mean), минимальное (min), максимальное (max), стандартное отклонение (stdev), сумму (sum) и т.д. Удобен для быстрого сравнения результатов разных запусков. Пример такого файла показан ниже.

% gw_id throughput_kbps
2 24.8493
  1. Идентификатор (ID): 

-1, -2, -0: Число в конце. Для per-gw это ID шлюза. Для per-ut — ID пользовательского терминала. Для global обычно 0. Для разработки тестов полезно будет изучить пример sat-environmental-variables-example, который показывает различные функции для определения путей к директориям, используемым модулем спутниковой связи, получение текущего рабочего каталога, пути к исполняемому файлу, пути к данным, пути к выводу и т.д. В примере sat-log-example показаны все способы журналирования результатом симуляции для модуля Satellite.

9.8 Отладка сценариев

После создания исходного кода сценария, его нужно добавить в список целей для сборки компилятором (если вы разместите ваш файл в директории scratch, то как рассказывалось ранее в главе 3, он будет добавлен в список целей автоматически). Для этого нужно выполнить следующие шаги:

./ns3 configure --enable-examples --enable-tests

Далее нужно проверить, что созданный вами тест добавился в список целей для сборки. Имя цели совпадает с именем теста (строго говоря имя цели определено в соответствующей данному тесту секции CMake-файла, и может быть любым. Но для удобства в проекте NS-3 используется правило, что имя цели совпадает с именем сценария, который она собирает). Для этого нужно выполнить команду:

./ns3 show targets | grep "<имя вашего теста>" 

Если команда не нашла ваш тест, вероятно вы ошиблись при его добавлении в CMake-файл. После того, как требуемая цель появилась в списке, выполняем сборку сценария:

./ns3 build

Следует отметить, что при сборке могут возникать ошибки компиляции которые не всегда связаны с ошибками в ваших файлах. В некоторых случаях причиной синтаксических ошибок могут быть устаревшие данные в кэше ninja(ninja инструмент для низкоуровневой автоматизации сборки). Такие ошибки можно распознать по абсурдному характеру сообщений об ошибке, например в таких случаях компилятор сообщает об ошибке в несуществующей в компилируемом файле строке кода или ошибке в преобразовании типа данных который даже не используется в данном коде. В таких случаях может помочь очистка кэша сборки и кэша ninja. Для этого нужно выполнить три шага (используется команда rm, будьте осторожны!):

  1. Полное удаление каталога сборки: 

    rm -rf build/
    
  2. Очистка кэша конфигурации: 

    rm -f ccache.conf build.ninja
    
  3. Снова выполнить конфигурирование и сборку, как было показано в этом разделе выше.

Как правило, новый сценарий начинает работать должным образом не сразу — требуется отладка. Чтобы её выполнить можно воспользоваться стандартным отладчиком gdb. Если вам нужно выяснить сбойную строку кода внутри библиотеки NS-3 или вашего кода, нужно использовать команду для запуска с дополнительными ключами (показано на примере сценария sat-cbr-example): При выполнении этой команды код вашего сценария и таблица отладочных символов будут переданы отладчику и появится приглашение командной строки. В этой строке введите команду run. Будет выполнен запуск сценария из под отладчика и когда сценарий «упадет», для просмотра стека вызовов наберите команду bt (backtrace). Таким же образом вы можете выполнить и другие команды отладчика.

./ns3 run «sat-cbr-example» --command-template=«gdb --args %s»

В сложных случаях для поиска и устранения утечек памяти можно воспользоваться анализатором утечек памяти Valgrind. Для этого из лога обычного запуска теста нужно выяснить полное имя исполняемого файла теста. Например, для теста sat-handover-hap полное имя будет выглядеть следующим образом: используем его при запуске Valgrind:

~/workspace_ns3.43/ns-3.43/build/contrib/sibgu-hap/examples/ns3.43-sat-handover-hap-default 
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=definite,indirect,possible --num-callers=20 --log-file=valgrind.log ~/workspace_ns3.43/ns-3.43/build/contrib/sibgu-hap/examples/ns3.43-sat-handover-hap-default

В результате работы Valgrind, исполнение теста сильно замедлится, но после его завершения у появится лог-файл valgrind.log который можно проанализировать инструментом визуализации Alleyoop (https://alleyoop.sourceforge.net/), либо с помощью нейросети. Более современный подход в поиске утечек памяти — это использование средств встроенных в компиляторы gcc, Clang так называемых санитайзеров(санитайзеры — инструменты динамического анализа кода. Они автоматически находят трудноуловимые ошибки в программах на C и C++ во время их выполнения). Для этого, на время отладки, нужно пересобрать симулятор с включенными санитайзерами. Пример показан ниже.

cd ~/workspace_ns3.43/ns-3.43

# Clean build directory
./ns3 clean

# Change configuration to enable sanitazers
./ns3 configure --build-profile=debug --enable-sanitizers --enable-examples --enable-tests

# Build
./ns3 build

Далее нужно запустить отлаживаемый тест. После его завершения (или падения) в консоль будет выведен отчет о замеченных отклонениях от нормы. Фрагмент такого отчета показан ниже.

Indirect leak of 8 byte(s) in 1 object(s) allocated from:

    #0 0x7b847eeb61e7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99

    #1 0x7b84624b97ba in __gnu_cxx::new_allocator<ns3::Ptr<ns3::SatFwdCarrierConf> >::allocate(unsigned long, void const*) /usr/include/c++/11/ext/new_allocator.h:127

    #2 0x7b84624b4fda in std::allocator<ns3::Ptr<ns3::SatFwdCarrierConf> >::allocate(unsigned long) /usr/include/c++/11/bits/allocator.h:185

Каждое сообщение об аномалии сопровождается дампом стека вызовов предшествовавших ее возникновению.

Заключение

Этой статьей мы завершаем цикл публикаций о модуле Satellite для симулятора сетей NS-3. Теперь в вашем распоряжении полный инструментарий NS-3 для моделирования космических сегментов и их интеграции с наземными сетями. Мы искренне надеемся, что этот цикл послужит надежным фундаментом для ваших исследовательских и инженерных проектов, а полученные навыки помогут в разработке решений для глобального, и не очень, космического интернета. Благодарим вас за интерес к нашим материалам, желаем успешных симуляций!

Работа выполнена в рамках Программы создания и развития центра НТИ на базе МФТИ, Физтех по направлению («сквозной» технологии) Национальной технологической инициативы «Перспективные технологии для космических систем и сервисов» при реализации комплексного научно-исследовательского и опытно-конструкторского проекта “Разработка комплексной среды моделирования и проектирования гибридных инфокоммуникационных сетей наземного, стратосферного и космического сегментов с использованием параметрического и структурного синтеза”.