L3VPN
Routing (Control plane)
Рассмотрим такую схему:
CE1 <static> PE1 <mpls> P <mpls> PE2 <static> CE2
Между CE и PE - маршрутизация (static, bgp, ospf). CE присылает свои префиксы, но ISP должен отделить эти префиксы от других и поместить с отдельную таблицу. Для этого клиент заводится в routing-instance (vrf).
PE должен передать принятые префиксы от клиента другому PE на удаленный конец, и затем отдать их удаленному CE2. Используем iBGP. В момент отправки префиксов с PE, нужно пометить их. Добавляем некое число - route-destinguisher (RD) - не идентифицирует клиента, просто делает префикс уникальным внутри процесса BGP. RD должен быть уникальным в пределах всей сети, поэтому зачастую используют IDrouter:число. RD - часть NLRI.
Типы RD:
- 2 byte: AS, 4 byte: идентификатор клиента
- 4 byte: router-ID, 2 byte: идентификатор клиента - можно руками не задавать, а поручить это маршрутизатору.
- 4 byte: 4 byte AS, 2 byte: идентификатор клиента
В inet.0 хранятся IPv4, не получится туда залить наши префиксы, т.к. они имеют совсем другую структуру.
NLRI - абстрактная структура данных. Роутеры до установления сессии должны совпадать хотя бы по 2-м address family.
Включаем protocols bgp family inet-vpn any - только после этого BGP будет способен передавать новые NLRI. По умолчанию, если включается какая-то конкретная family, то требуется указать все family, которые будут передаваться через MP-BGP. То есть добавляем сюда и family inet обязательно.
Под новые NLRI создается своя таблица: bgp.l3vpn.0. Префиксы хранятся вместе с RD. Таблица используется только на control plane, не для форвардинга. Для форвардинга будет использоваться отдельная таблица для VRF. В ней префиксы будут храниться в обычном IPv4 формате. Для этого нужно убрать RD и разложить префиксы по нужным VRF. То есть в сети должен существовать некий идентификатор клиента.
Route target (RT) - не часть NLRI, это атрибут, который передается внутри объекта вместе с NLRI. RT - extended community типа 2. По сути будет определять какому VRF относится префикс.
С помощью RT можно для клиента обеспечить связность не только full mesh, но и более сложные топологии: 1 ко всем, 2 между собой, 3-й только с конкретным сайтом.
NLRI с RT прилетает на удаленный PE, префикс запихивается в нужный VRF, убирается RD, сохраняем префикс в виде IPv4. По настроенному протоколу PE<>CE передает префикс CE.
BGP: по дефолту передает только маршруты, полученные по BGP. Но с VRF другое поведение: если конфигурируем VRF и в VRF пишет target, а не policy, то роутер берет все маршруты из этого VRF, присоединяет к ним target, и отправляет по MP-BGP.
Когда проанонсированный префикс прилетает соседу (используя vpn family), тот: смотрит на target, ищет у себя target. Если VRF с таким target нет, то BGP-update отбрасывается (даже не попадают в hidden), он не знает в какую таблицу его запихнуть. Как проверить, что все-таки update прилетает: включить traceoptions. Т.е. на P роутере prefix клиента отбросится. Но до PE2 по iBGP все-равно анонс долетит, но будет скрытым (не отрезолвился next-hop, он не попал в inet.3). Если prefix все-таки не прилетает даже в hidden, то скорей всего проблема с RT.
Forwarding
Допустим, к CE1 подключено устройство с default route, пакет идет на CE1. CE1 по BGP передает трафик к PE1. На PE1 пакет попадает в vrf1.table.inet.0, т.к. на PE1 интерфейс в сторону CE1 добавлен в VRF клиента. Forwarding next-hop: P-router (по IGP). P-router принимает пакет и не знает что с ним дальше делать. Схема не рабочая
Будем туннелировать пакеты от PE1 (не обязательно в mpls). Но рассматриваем mpls.
- LSP на PE1 в inet.3: PE2: push 20 -> P. BGP резолвит next-hop для PE2, подставляет в inet.0.
- P смотрит в mpls.0: 20 pop.
- На PE2 прилетает голый ip пакет. PE2 делает lookup в inet.0, т.к. интерфейс, с которого пришел пакет - принадлежит master RI и сам пакет - просто ip. В inet.0 не будет нужного маршрута => тоже схема не рабочая.
Делаем так, чтобы PE2 понял, что lookup нужно производить внутри VRF. RT и RD не проканают, т.к. они существуют только на уровне control plane, и не причастны к передаче трафика.
Какой-нибудь header можем использовать как идентификатор, что нужно смотреть в определенной таблице. Берем MPLS заголовок.
- Исходный VRF каждому пакету выделяет уникальную для себя метку. Пакет будет иметь следующий вид: label:RD:prefix/mask.
- Добавлять метку будет egress, удаленный PE2 роутер. Поэтому выделенную метку нужно проанонсировать с PE1 на PE2 по MP-BGP. Family vpn: label:prefix/mask.
- Т.к. на PE2 префикс прилетает с меткой (смотрим в таблицу bgp.l3vpn vpn label), то для PE2 это означает, что с другой стороны пакеты ждут с этой меткой. Т.е. PE2 добавляет выделенную метку, затем resolve next-hop. В нашем случае произойдет следующее: push 20 (для LSP) push 50 (для VRF) -> P.
- На P делается 20 pop.
- На PE1 приходит пакет: 50:RD:prefix/mask. Пакет попадает в mpls.0, где должна быть запись: 50: pop -> vrf1. Такая запись будет создана, как только будет создан сам VRF (ему назначается определенная метка и запись инсталлируется в mpls.0).
- На PE1 далее метка снимается, RD снимается, пакет идет на второй lookup внутри таблицы vrf1. И далее пакет направляется к нужному next-hop, согласно таблицы vrf1.
На PE2 делается 2 lookup.
Такая схема будет работать только если включить vrf-table-label.
В каких случаях нам может потребоваться делать второй lookup внутри VRF: если хотим осуществлять какие-то дополнительные функции для клиентов на основании ip внутри VRF - посчитать трафик, пофильтровать, пополисить... по ip заголовку. vrf-table-label заставляет роутер назначать метку на VRF и делать второй lookup. В основном этой схемой и пользуются.
Но на самом деле Juniper по дефолту работает так: метка назначается не на VRF, а на next-hop, с которого исходно пришли клиентские маршруты. Каждому next-hop своя метка. Т.о. на PE2 в mpls.0: 51 pop -> CE1 next-hop, 52 pop -> CE2 next-hop. Это позволяет не делать второй lookup.
Cisco по дефолту назначает метки для prefix. Но это не очень удобно, когда от клиента приходит много префиксов и тем самым занимается ASIC для хранения всех этих меток.
CE<>PE eBGP
У клиента одна и та же AS с двух сторон (AS 65000) => PE1 (AS 10) получает префикс с AS-path 65000 * => на PE2 сработает split horizing, и он не будет анонсировать CE2 => решаем проблему.
- На PE1 в VRF под протоколом BGP: advertise peer-as - отключает split horizont. AS path поменяется: 10 65000 *. СЕ2 принимает маршрут, но по идее должен его отбросить, т.к. в AS-path видит свою AS. => на CE2 отключаем проверку на loop: routing-options autonomous-system loops 2.
- На РЕ1 в VRF под протоколом BGP: as-override - отключает split horizing + ищет в AS-path соседскую AS и заменяет ее на свою. Новый AS-path: 10 10. На CE2 проблемы не возникнет.
- Если у клиентов private AS => remove private. Можно включить в разных местах.
- На PE1 внутри VRF настраиваем AS CE1: routing-options autonomous-system <AS-CE1> + routing-instance <instance> routing-options autonomous-system independent-domain - исходные атрибуты BGP от CE1 сохраняются в новый атрибут: outer-set, который добавится при анонсе в iBGP провайдера. На PE2 тоже настраиваем independent-domain, который раскроет outer-set. Т.о. при передаче префикса CE2 AS-path не будет заполнен (при iBGP AS-path пустой). Внутри VRF настраиваем internal BGP. Также этот способ дает возможность сохранить local-preference от CE1.
© Наталия Бобкова 2014—2022