Перейти к содержанию

Туннели MPLS TE

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

Туннели MPLS TE: таблица LSP и размещённые пути на графе

Вкладка 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 туннель/путь 07, по умолчанию 7 пул допуска RSVP-TE (0 - самый сильный)
hold_priority туннель/путь 07, по умолчанию равен 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_0unreserved_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 (hop strict должен быть прямым линком от предыдущего 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