Spoke to spoke мультикаст в сетях DMVPN
Про настройку и диагностику технологии DMVPN в интернете написано немало статей. Однако про использование мультикаста поверх DMVPN лучшее, что мне удалось найти – это маленькая заметка в Configuration Guide.
“In DMVPN, it is recommended to configure a Rendezvous Point (RP) at or behind the hub. If there is an IP multicast source behind a spoke, the ip pim spt-threshold infinity command must be configured on spokes to avoid multicast traffic going through spoke-to-spoke tunnels.”
Давайте выясним, в чем на самом деле заключается необходимость этой команды. Тестовая схема выглядит следующим образом.
Как можно заметить, это самый обыкновенный DMVPN Phase 2, собранный в GNS3. Интерфейсы Loopback на каждом маршрутизаторе позволяют смоделировать клиентские подсети; также логично разместить RP на Hub-маршрутизаторе как центральной точке логической топологии. Для удобства адресации примем Hub = R1, Spoke1 = R2, Spoke2 = R3, Internet = R4.
Настроим PIM и RP внутри DMVPN облака.
Hub |
Spoke1 |
Spoke2 |
interface Loopback0 ip address 1.1.1.1 255.255.255.255 ip pim sparse-mode interface Tunnel0 ip address 192.168.0.1 255.255.255.0 no ip redirects no ip split-horizon eigrp 1 ip pim sparse-mode ip nhrp map multicast dynamic ip nhrp network-id 1 tunnel source FastEthernet0/0 tunnel mode gre multipoint tunnel vrf A ip pim rp-address 1.1.1.1
|
interface Loopback0 ip address 2.2.2.2 255.255.255.255 ip pim sparse-mode interface Tunnel0 ip address 192.168.0.2 255.255.255.0 no ip redirects ip pim sparse-mode ip nhrp network-id 1 ip nhrp nhs 192.168.0.1 nbma 192.168.14.1 multicast tunnel source FastEthernet0/1 tunnel mode gre multipoint tunnel vrf A ip pim rp-address 1.1.1.1
|
interface Loopback0 ip address 3.3.3.3 255.255.255.255 ip pim sparse-mode interface Tunnel0 ip address 192.168.0.3 255.255.255.0 no ip redirects ip pim sparse-mode ip nhrp network-id 1 ip nhrp nhs 192.168.0.1 nbma 192.168.14.1 multicast tunnel source FastEthernet1/0 tunnel mode gre multipoint tunnel vrf A ip pim rp-address 1.1.1.1 |
На данном этапе есть связность между Spoke, а также необходимые протоколы управления групповым вещанием. Самое время подписаться на мультикаст поток на Spoke1.
Spoke1(config)#int lo 0
Spoke1(config-if)#ip igmp join-group 224.1.1.1
Spoke1#sho ip mroute
Список OIL (outgoing interface list) пуст, что и является причиной потери потока. Или не является? Почему же тогда прошёл самый первый пакет? Давайте взглянем на Hub за пару секунд до того.
Hub#sho ip mroute
<output omitted>
(*, 224.1.1.1), 00:00:13/00:03:16, RP 1.1.1.1, flags: S
Incoming interface: Null, RPF nbr 0.0.0.0
Outgoing interface list:
Tunnel0, Forward/Sparse, 00:00:13/00:03:16
(*,G) содержит Tunnel0, что ожидаемо; RPF сосед также пока неизвестен, поскольку ни один пакет из потока ещё не прошёл через Hub. А дальше следите за руками:
- Spoke2 шлёт самый первый мультикаст пакет внутри unicast сообщения RP-Register;
- Hub, он же RP, получает RP-Register и выполняет следующие два действия: отправляет пакет согласно OIL (Tunnel0); кроме того, отправляет PIM Join в сторону источника потока (Tunnel0);
- В режиме PIM-SM входящий интерфейс (IIF, incoming interface) не может присутствовать в OIL (RPF check), поскольку это может породить петлю; следовательно, Tunnel0 необходимо исключить из OIL – в этот момент Spoke2 теряет поток.
Суть проблемы кроется в NBMA (non-broadcast multiple access) поведении DMVPN: Spoke2 логически находится в одном широковещательном сегменте со Spoke1, хотя физически это совсем не так (а Вы думали, Frame-Relay жил, Frame-Relay жив, Frame-Relay будет жить; надеюсь, это шутка). Впрочем, решение задачи довольно простое – надо явно указать Hub, что Tunnel0 следует рассматривать не как один интерфейс, а как набор нескольких.
Hub#sho run | i Tunnel0|nbma
interface Tunnel0
ip pim nbma-mode
Теперь таблица маршрутизации мультикаста правильная.
Hub#sho ip mroute
(*, 224.1.1.1), 00:03:51/00:03:27, RP 1.1.1.1, flags: S
Incoming interface: Null, RPF nbr 0.0.0.0
Outgoing interface list:
Tunnel0, 192.168.0.2, Forward/Sparse, 00:00:02/00:03:27
(3.3.3.3, 224.1.1.1), 00:03:29/00:02:25, flags: JT
Incoming interface: Tunnel0, RPF nbr 192.168.0.3
Outgoing interface list:
Tunnel0, 192.168.0.2, Forward/Sparse, 00:00:02/00:03:27
Поскольку Tunnel0 теперь работает как несколько интерфейсов, таблица маршрутизации мультикаста содержит не только сам интерфейс, но и адреса как получателя (192.168.0.2), так и отправителя (192.168.0.3) потока. Стоит отметить ещё одну любопытную особенность поведения DMVPN, когда поток мультикаста идёт со стороны Hub в сторону Spoke. По умолчанию, DMVPN отправляет мультикаст каждому Spoke (ip nhrp map multicast dynamic), что успешно используют протоколы маршрутизации, отправляя служебную информацию или обновления мультикастом. Однако если сеть является географически распределённой (например, несколько регионов), такое поведение может быть нежелательным: мультикаст, отправленный во все регионы, в том числе туда, где нет PIM подписки, занимает полосу, после чего его отбрасывают все Spoke, кроме того, кому поток был действительно нужен. Такое поведение можно исправить использованием PIM NBMA режима для DMVPN, что позволяет различать Spoke по адресам на уровне мультикаста и отправлять поток только тем регионам, где на него есть подписка.
Настало время ещё раз проверить связность между Spoke для мультикаста.
Spoke2#ping 224.1.1.1 so lo 0 rep 1000 Type escape sequence to abort.
Sending 1000, 100-byte ICMP Echos to 224.1.1.1, timeout is 2 seconds:
Packet sent with a source address of 3.3.3.3
Reply to request 0 from 2.2.2.2, 176 ms..…
Ничего не поменялось, но мы упорные. Начнём проверять по порядку, начиная с Hub.
Hub#sho ip mroute
(*, 224.1.1.1), 00:52:32/00:02:58, RP 1.1.1.1, flags: S
Incoming interface: Null, RPF nbr 0.0.0.0
Outgoing interface list:
Tunnel0, 192.168.0.2, Forward/Sparse, 00:02:12/00:02:58
(3.3.3.3, 224.1.1.1), 00:01:30/00:01:31, flags: PT
Incoming interface: Tunnel0, RPF nbr 192.168.0.3
Outgoing interface list: Null
(S,G) запись неактивна (флаг P) на Hub, соответственно, OIL пуст. Очевидно, что это дело рук Spoke1, больше некому.
Spoke1#sho ip mroute
<output omitted>
(*, 224.1.1.1), 00:52:44/stopped, RP 1.1.1.1, flags: SJCL
Incoming interface: Tunnel0, RPF nbr 192.168.0.1
Outgoing interface list:
Loopback0, Forward/Sparse, 00:09:18/00:02:26
(3.3.3.3, 224.1.1.1), 00:01:39/00:01:20, flags: LJT
Incoming interface: Tunnel0, RPF nbr 192.168.0.3
Outgoing interface list:
Loopback0, Forward/Sparse, 00:01:39/00:02:26
Вроде бы таблица правильная… Но нет: RPF сосед – Spoke 2, а должен быть Hub. Посмотрим внимательно на весь процесс ещё раз.
- Spoke2 отправляет первый пакет потока внутри RP-Register;
- Hub пересылает пакет Spoke1 и начинает построение SPT дерева в сторону Spoke2;
- Spoke1 получает первый пакет, создаёт новое состояние для потока в таблице маршрутизации, высылает ответ.
- Spoke1 осознаёт, что RPF сосед для источника мультикаста – это Spoke2, поэтому он отправляет SPT-Join в сторону Spoke2. Однако в силу NBMA поведения DMVPN, физически SPT-Join идёт в сторону Hub. Последний его с радостью отбрасывает, поскольку внутри пакета в качестве RPF соседа указан Spoke2.
- IIF для RPT и SPT один и тот же, Tunnel0, поэтому Spoke1 отправляет сообщение (*,G) Prune в сторону Hub, где он и обрабатывается.
В результате, Hub отключает у себя (*,G) запись, а Spoke1 не может завершить создание (S,G) записи в таблице маршрутизации, что приводит к нарушению связности между Spoke.Корень зла в этом случае – SPT-switchover: между Spoke нет прямой связности для мультикаста, единственный доступный путь – через Hub. В конце концов, мы пришли к команде, которая упоминается в Configuration Guide – ip pim spt-threshold infinity. Неужели теперь связность появится?
Spoke2#ping 224.1.1.1 so lo 0 rep 1000 Type escape sequence to abort.
Sending 1000, 100-byte ICMP Echos to 224.1.1.1, timeout is 2 seconds:
Packet sent with a source address of 3.3.3.3
Reply to request 0 from 2.2.2.2, 112 ms
Reply to request 1 from 2.2.2.2, 84 ms
Reply to request 2 from 2.2.2.2, 76 ms
Reply to request 3 from 2.2.2.2, 80 ms
Reply to request 4 from 2.2.2.2, 52 ms
Reply to request 5 from 2.2.2.2, 48 ms
На данном этапе мультикаст работает, как и ожидалось вначале. Поток может быть передан в любом направлении (hub-spoke, spoke-spoke, spoke-hub), причём только в сторону тех Spoke, которые на него подписались. Стоит отметить, однако, что передача мультикаста напрямую между Spoke чревата повышением нагрузки на канал вследствие рассылки мультикаста внутри направленных пакетов; канал до Spoke на такую нагрузку, как правило, не рассчитан, что может привести как к проблемам с масштабированием решения, так и к ухудшению связности для существующих приложений.
В статье мы рассмотрели, что необходимо добавить к обычному DMVPN Phase 2, чтобы успешно запустить поверх него мультикаст. К тонким моментам можно отнести, пожалуй, только режим PIM NBMA и SPT-switchover – это единственное отличие от общеизвестных настроек DMVPN Phase 2.