Туннели MPLS TE¶
В дополнение к топологиям на основе YAML и
атрибутам Traffic Engineering, диаграмма может
объявлять туннели MPLS TE (в стиле RSVP-TE или SR-TE) в секции верхнего
уровня lsps:. Topolograph выполняет для них размещение CSPF (Constrained
Shortest Path First) - те же ограничения по пропускной способности,
affinity и SRLG, что и у реального маршрутизатора, без какой-либо
сигнализации - и визуализирует результат.

Вкладка LSP tunnels перечисляет каждый путь с его статусом размещения, причиной, по которой путь не удалось построить, пропускной способностью и приоритетами; выбор узла показывает туннели, для которых он является ingress, transit или egress, а размещённые пути отрисовываются на сетевой диаграмме.
Пока только диаграммы YAML
lsps: доступен на диаграммах, основанных на YAML. Поддержка туннелей,
сообщаемых Watcher-ом в реальном времени, планируется в одном из
следующих релизов.
Туннель в YAML¶
lsps:
TUN_R1_R3: # key = tunnel name
src: 10.10.10.1
dst: 10.10.10.3
metric_type: te # igp (default) | te
bandwidth: 2G # applies to every path unless overridden
setup_priority: 7
admin_groups:
exclude-any: [red]
color: "#ff9900"
autoroute: false # see "autoroute" below
paths: # = LSPs; omit entirely for one dynamic primary
primary:
ero:
- 10.10.10.2 # plain string = loose hop
- {node: 10.10.10.3, hop: strict} # explicit form for a strict hop
secondary:
role: standby
bandwidth: 1G # overrides the tunnel-level default
srlg_exclude: [1001]
Справочник ключей¶
| ключ | уровень | значения/формат | значение |
|---|---|---|---|
lsps |
верхний уровень | словарь, имя туннеля → тело | опциональная секция рядом с nodes/edges |
src, dst |
туннель | имя узла (формат IP-адреса) | конечные точки туннеля |
metric_type |
туннель | igp (по умолчанию) | te |
по какой метрике CSPF выполняет оптимизацию |
bandwidth |
туннель/путь | 2G, 500M или число в bps |
требуемая пропускная способность; путь переопределяет значение по умолчанию туннеля |
setup_priority |
туннель/путь | 0–7, по умолчанию 7 |
пул допуска RSVP-TE (0 - самый сильный) |
hold_priority |
туннель/путь | 0–7, по умолчанию равен setup_priority |
пул, в котором удерживается резервирование; не может быть слабее setup priority |
admin_groups |
туннель/путь | словарь: exclude-any / include-any / include-all → список имён |
фильтр affinity |
srlg_exclude |
путь | список int | ограничение SRLG |
color |
туннель | цвет CSS | цвет подсветки на сетевой диаграмме |
autoroute |
туннель | bool, по умолчанию false |
см. ниже |
paths |
туннель | словарь, имя пути → тело; если опущено - один динамический primary |
LSP туннеля |
role |
путь | primary (по умолчанию) | secondary | standby |
роль пути |
ero |
путь | список: 10.10.10.2 (loose hop) или {node: ..., hop: strict} |
явный маршрут |
Путь наследует bandwidth, setup_priority, hold_priority и
admin_groups от туннеля, если не задаёт их сам. srlg_exclude и ero
не наследуются - указание srlg_exclude на уровне туннеля не имеет
эффекта, задавайте его на каждом пути, которому это нужно.
Линки объявляют те же атрибуты TE, что описаны на
странице Traffic Engineering
(temetric, max_rsrv_link_bw, admin_group/affinity, srlg,
unreserved_bw_0…unreserved_bw_7) - отдельного именования для целей MPLS
нет.
autoroute¶
Сигнализированный LSP не перенаправляет трафик сам по себе - это
соответствует реальному поведению RSVP-TE/SR-TE: без autoroute announce
(или явного статического маршрута, указывающего на туннель) туннель - это
просто зарезервированная пропускная способность, невидимая для вычисления
пути в стиле IGP. Установите autoroute: true на туннеле, чтобы он
действовал как сокращение пересылки в запросах пути "из конца в конец" (см.
with_lsps ниже) - реальный аналог включения autoroute на headend.
Setup и holding priority¶
0 - самый сильный приоритет, 7 - самый слабый. Если hold_priority не
задан, он следует за setup_priority, как и у маршрутизатора при priority
<setup> без второго значения.
Туннель, установленный на сильном приоритете, но удерживаемый на слабом,
был бы вытесняемым сразу после сигнализации, поэтому такая комбинация
отклоняется: hold_priority должен быть как минимум таким же сильным, как
setup_priority (setup_priority: 0 с hold_priority: 7 - ошибка
валидации, setup_priority: 7 с hold_priority: 0 - допустимо).
Неподдерживаемые (эксплуатационные) ключи¶
rro, oper_status, active_lsp_name и любой ключ label_*
не поддерживаются в lsps: - они описывают состояние живой сигнализации
(Record Route, текущий статус, активный путь), а не декларируемое
намерение, и имеют смысл только тогда, когда их сообщает реальный watcher.
Если вы укажете один из них, будет выдана ошибка валидации.
Расчёт пути через CSPF¶
При каждом расчёте Topolograph обрабатывает пути в порядке setup_priority
(соглашение RSVP-TE: 0 - наивысший приоритет), по тем же правилам, что
применил бы реальный маршрутизатор:
- отфильтровывает линки, у которых недостаточно пропускной способности в
запрошенном пуле
setup_priority, которые не удовлетворяют фильтру affinity или входят в исключённый SRLG; - выполняет поиск кратчайшего пути по оставшимся линкам, учитывая любой
ero(hopstrictдолжен быть прямым линком от предыдущего hop - LSP завершается отказом, а не тихо обходит его); - вычитает размещённую пропускную способность из этого пула (и из каждого пула с более низким приоритетом) перед размещением следующего пути.
Размещение никогда не изменяет анонсируемые атрибуты TE
(unreserved_bw_*) - потреблённая ёмкость отслеживается отдельно, поэтому
повторный запуск размещения всегда начинается с реальных анонсируемых
значений.
Равнозначные варианты ECMP разрешаются детерминированно: сначала по наименьшему числу hop-ов, затем по лексикографическому порядку имён узлов.
Получение результатов по запросу на установление LSP¶
GET /api/graph/{graph_time}/lsps и GET /api/graph/{graph_time}/lsps/{name}
возвращают результат размещения каждого пути вместе с его объявленной
конфигурацией:
{
"name": "TUN_R1_R3",
"src": "10.10.10.1",
"dst": "10.10.10.3",
"paths": {
"primary": {
"placed": true,
"reason": null,
"cost": 20,
"path": ["10.10.10.1", "10.10.10.2", "10.10.10.3"]
},
"secondary": {
"placed": false,
"reason": "insufficient bandwidth",
"cost": null,
"path": []
}
}
}
reason словами объясняет, почему путь не удалось построить. Рядом с ним
reason_code даёт машиночитаемую категорию, а
binding_constraints называет то, что фактически блокирует размещение:
reason_code |
значение | что делать |
|---|---|---|
disconnected |
пути нет, даже если снять все ограничения | чинить топологию |
constraints_unsatisfiable |
путь существует, но запрос слишком строгий | ослабить ограничения из binding_constraints (bandwidth, affinity, srlg) |
ero_strict_hop_unreachable |
у строгого hop нет линка от предыдущего hop | исправить ero |
endpoint_not_found |
src/dst отсутствует в графе |
исправить конечную точку |
Несколько значений в binding_constraints означают, что для установления
LSP достаточно снять любой один из этих атрибутов.
Полезные фильтры на эндпоинте списка:
# Which tunnels failed to place, and why
graph.lsps_list(status="unplaced")
# Which tunnels cross a given node or link (pre-maintenance impact check)
graph.lsps_list(via_node="10.10.10.2")
graph.lsps_list(via_edge="10.10.10.1,10.10.10.2")
Сколько TE-полосы пропускания осталось на линке с учётом всех размещённых туннелей:
graph.edges_list(include=["lsp_left_bw"])
# -> ..., "lsp_left_bw_7": ..., "lsp_reserved_bw": "7Gbps",
# "lsp_left_bw": "3Gbps", "lsp_bandwidth_usage": "7Gbps/3Gbps"
Путь CSPF без объявления туннеля¶
cspf_path отвечает на вопрос "какой путь удовлетворяет этим ограничениям
и какой у него стоимость" - вычисление кратчайшего пути с фильтрацией по
ограничениям, тот же класс запроса, что и обычный кратчайший путь. Ничего
не создаётся и не сохраняется:
result = graph.cspf_path(
"10.10.10.1", "10.10.10.7",
bandwidth="5G",
admin_exclude_any=["red"],
)
# {'path': [...], 'cost': 42, 'reason': ''}
# or, if nothing fits: {'path': [], 'cost': None, 'reason': 'no path ... satisfies the requested constraints: ...'}
Ответ учитывает пропускную способность, которую удерживают уже
объявленные туннели: на топологии с секцией lsps: проверка выполняется
относительно того, что осталось на каждом линке после размещения, а не
относительно агрегированного значения, поэтому путь никогда не прокладывается
через уже занятую ёмкость. Ограничения оцениваются по каждому приоритету
setup отдельно, так что линк может быть заполнен на одном приоритете и всё
ещё иметь запас на более сильном.
Ограничения affinity (admin_exclude_any, admin_include_any,
admin_include_all) сопоставляются с именами affinity на линке.
Топологии, полученные из реальной сети, анонсируют административную группу
как битовую маску, поэтому include-any/include-all по именам на таких
графах не находит совпадений, и ответом будет "путь отсутствует" - используйте там exclude-any или топологию YAML с именованными affinity.
Путь из конца в конец через туннели (with_lsps)¶
По умолчанию graph.paths.shortest(src, dst) - это обычный путь IGP, на
который не влияет ни один туннель в графе, так же как реальная
IP-пересылка без autoroute. Передайте with_lsps=True, чтобы учитывать
туннели с autoroute: true как сокращения пересылки:
graph.paths.shortest("10.10.10.1", "10.10.10.4") # plain IGP path
graph.paths.shortest("10.10.10.1", "10.10.10.4", with_lsps=True) # via active autoroute tunnels
Что сломается при отказе линка?¶
edge_failure_reaction прогнозирует влияние на всю сеть при отказе одного
или нескольких линков - линки, которые теряют трафик, и линки, которые
принимают его на себя:
graph.paths.edge_failure_reaction([("10.10.10.1", "10.10.10.2")])
# {'isGraphStillConnected': True, 'affectedLinks': {...}, 'disjointedNodes': []}
Чтобы посмотреть на тот же вопрос в разрезе туннелей, объедините это с
lsps_list(via_edge=...) - так видно, какие туннели проходят через линк,
прежде чем проверять влияние его отказа.
Связанные страницы: Топологии на основе YAML · Атрибуты Traffic Engineering · Python SDK