Если вы хоть раз настраивали MPLS L3VPN, то у вас не возникнет сомнения в том, что весь подход вертится вокруг BGP. Будучи протоколом маршрутизации с развитым чувством собственного достоинства (в конце концов, он является основой для интернета), BGP использует внушительный список атрибутов префикса, который лежит в основе алгоритма выбора лучшего маршрута. Несмотря на неприличную длину этого списка, большинство параметров предназначены для обеспечения детерминированности результата алгоритма, а не для управления трафиком руками инженера. Впрочем, иногда даже самые популярные параметры не подходят для решения определённой задачи. Если вы видите EIGRP в связке с L3VPN, возможно, это наш сегодняшний пациент.

Сестра, топологию:

R1-R3 – это PE-маршрутизаторы, которые используют в ядре OSPF наряду с LDP. Они также обеспечивают связность между площадками с использованием разных IGP: R1↔R4 ≡ OSPF, R2↔R5 ≡ EIGRP, R3↔R6 ≡ eBGP. Клиентские устройства CE, R4-R6, находятся в одном и том же VRF. R4 и R5 предоставляют R6 доступ к некоему сервису, который расположен по адресу 8.8.8.8/32.

Настройка R1 в качестве образца:

R1(config)#vrf definition A
R1(config-vrf)# rd 1:1
R1(config-vrf)# route-target export 1:1
R1(config-vrf)# route-target import 1:1
R1(config-vrf)# address-family ipv4
R1(config)#interface Loopback0
R1(config-if)# ip address 1.1.1.1 255.255.255.255
R1(config)#interface FastEthernet0/0
R1(config-if)# vrf forwarding A
R1(config-if)# ip address 192.168.14.1 255.255.255.0        
R1(config)#interface FastEthernet1/0
R1(config-if)# ip address 192.168.13.1 255.255.255.0
R1(config)#interface FastEthernet1/1
R1(config-if)# ip address 192.168.12.1 255.255.255.0
R1(config)#router ospf 2 vrf A
R1(config-router)# redistribute bgp 123 subnets
R1(config-router)# network 0.0.0.0 255.255.255.255 area 0
R1(config)#router ospf 1
R1(config-router)# mpls ldp autoconfig
R1(config-router)# router-id 1.1.1.1
R1(config-router)# network 0.0.0.0 255.255.255.255 area 0
R1(config)#router bgp 123
R1(config-router)# bgp router-id 1.1.1.1
R1(config-router)# no bgp default ipv4-unicast
R1(config-router)# neighbor L3VPN peer-group
R1(config-router)# neighbor L3VPN remote-as 123
R1(config-router)# neighbor L3VPN update-source Loopback0
R1(config-router)# neighbor 2.2.2.2 peer-group L3VPN
R1(config-router)# neighbor 3.3.3.3 peer-group L3VPN
R1(config-router)# address-family vpnv4
R1(config-router-af)#  neighbor L3VPN send-community both
R1(config-router-af)#  neighbor 2.2.2.2 activate
R1(config-router-af)#  neighbor 3.3.3.3 activate
R1(config-router-af)# exit-address-family
R1(config-router)# address-family ipv4 vrf A
R1(config-router-af)#  redistribute ospf 2

На CE-маршрутизаторах всё ещё аскетичнее:

R6(config)#interface Loopback0
R6(config-if)# ip address 6.6.6.6 255.255.255.255
R6(config)#interface FastEthernet0/0
R6(config-if)# ip address 192.168.36.6 255.255.255.0
R6(config)#router bgp 6
R6(config-router)# bgp router-id 6.6.6.6
R6(config-router)# no bgp default ipv4-unicast
R6(config-router)# neighbor 192.168.36.3 remote-as 123
R6(config-router)# address-family ipv4
R6(config-router-af)#  network 6.6.6.6 mask 255.255.255.255
R6(config-router-af)#  neighbor 192.168.36.3 activate

Интерфейсы loopback эмулируют доступность некого сервиса:

R4(config)#interface Loopback1
R4(config-if)# ip address 8.8.8.8 255.255.255.255
R5(config)#interface Loopback1
R5(config-if)# ip address 8.8.8.8 255.255.255.255

Посмотрим, есть ли в принципе связность между R6 и 8.8.8.8:

R6#ping 8.8.8.8 source loopback 0
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 8.8.8.8, timeout is 2 seconds:
Packet sent with a source address of 6.6.6.6 
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 52/60/80 ms

Основная цель такой схемы – обеспечить отказоустойчивый доступ R6 к 8.8.8.8/32 через R4 и R5, именно поэтому BGP-сессии построены между PE-маршрутизаторами напрямую. R1 и R2 должны считать префиксы от IGP лучшими с точки зрения BGP RIB (это локальные маршруты); как следствие, R3 должен получить оба маршрута, по одному от каждого из соседей.

R3#sho bgp vpnv4 unicast all 
BGP table version is 13, local router ID is 3.3.3.3
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, 
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, 
              x best-external, a additional-path, c RIB-compressed, 
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 1:1 (default for vrf A)
 *>i 4.4.4.4/32       1.1.1.1                  2    100      0 ?
 *>i 5.5.5.5/32       2.2.2.2             103040    100      0 ?
 *>  6.6.6.6/32       192.168.36.6             0             0 6 i
 *>i 8.8.8.8/32       2.2.2.2             103040    100      0 ?
 *>i 192.168.14.0     1.1.1.1                  0    100      0 ?
 *>i 192.168.25.0     2.2.2.2                  0    100      0 ?

По странному стечению обстоятельств R3 получил только один префикс вместо двух. Вполне вероятно, что R1 вовсе не слал ничего о 8.8.8.8/32:

R1#sho bgp vpnv4 unicast all
BGP table version is 13, local router ID is 1.1.1.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, 
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, 
              x best-external, a additional-path, c RIB-compressed, 
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 1:1 (default for vrf A)
 *>  4.4.4.4/32       192.168.14.4             2         32768 ?
 *>i 5.5.5.5/32       2.2.2.2             103040    100      0 ?
 *>i 6.6.6.6/32       3.3.3.3                  0    100      0 6 i
 r>i 8.8.8.8/32       2.2.2.2             103040    100      0 ?
 r                    192.168.14.4             2         32768 ?
 *>  192.168.14.0     0.0.0.0                  0         32768 ?
 *>i 192.168.25.0     2.2.2.2                  0    100      0 ?

R1 считает 8.8.8.8/32, полученный от R2, лучшим маршрутом (символ ‘>’). Поскольку этот префикс получен по iBGP, он не попадает в обновления, предназначенные обычным iBGP-соседям. Почему же выбор R1 именно такой? Согласно алгоритму выбора лучшего маршрута, только weight и local preference имеют больший приоритет, чем локальность префикса. Более того, по умолчанию локальные маршруты получают атрибут weight со значением 32768. По всем правилам получается так, что 8.8.8.8/32 от OSPF должен с большим отрывом победить маршрут от R2. Что же не так?

R1#sho bgp vpnv4 unicast all 8.8.8.8/32
BGP routing table entry for 1:1:8.8.8.8/32, version 13
Paths: (2 available, best #1, table A, RIB-failure(17) - next-hop mismatch)
  Not advertised to any peer
  Refresh Epoch 1
  Local
    2.2.2.2 (metric 2) from 2.2.2.2 (2.2.2.2)
      Origin incomplete, metric 103040, localpref 100, valid, internal, best
      Extended Community: RT:1:1 Cost:pre-bestpath:128:103040 0x8800:32768:0 
        0x8801:1:2560 0x8802:65281:25600 0x8803:65281:1500 0x8806:0:134744072
      mpls labels in/out nolabel/22
  Refresh Epoch 1
  Local
    192.168.14.4 from 0.0.0.0 (1.1.1.1)
      Origin incomplete, metric 2, localpref 100, weight 32768, valid, sourced
      Extended Community: RT:1:1 OSPF DOMAIN ID:0x0005:0x000000020200 
        OSPF RT:0.0.0.0:2:0 OSPF ROUTER ID:192.168.14.1:0

Зубрить сухие цифры – крайне неблагодарное занятие, поэтому весьма неплохо иметь под рукой шпаргалку с номерами и содержанием community для OSPF и EIGRP. Впрочем, виновник торжества сам по себе имеет довольно выразительное название – Cost:pre-bestpath:128:103040.

Роль cost community в топологиях L3VPN с EIGRP вполне прозаична. Представим две площадки, A и B, которые соединены между собой посредством быстрого L3VPN как основного пути и через выделенную линию в качестве запасного маршрута. В произвольный момент времени в недрах Площадки-А возникает Префикс-А, обновление о котором распространяется по обоим маршрутам. В такой ситуации возникает race condition:

  • Обновление о Префиксе-А достигает Площадки-В вначале через MPLS backbone. PE устанавливает новый префикс в BGP RIB, передает его в EIGRP (попутно восстанавливая метрику из community) и анонсирует новый маршрут на Площадке-В. Выделенная линия имеет худшую метрику, поэтому основной путь до Префикса-А лежит через ядро MPLS, что и требовалось реализовать.

  • Обновление о Префиксе-А достигает Площадки-В вначале через выделенную линию. При таком раскладе Префикс-А попадает в BGP RIB через EIGRP локально, поэтому когда соответствующее обновление приходит со стороны MPLS, оно не может стать лучшим с точки зрения BGP. Как следствие, Площадка-В начинает использовать выделенную линию в качестве основного пути, что не соответствует требуемому поведению.

Cost community является одним из решений описанной проблемы. Этот инструмент позволяет BGP рассматривать специальную метрику в определённом месте алгоритма выбора лучшего пути (в нашем случае – в самом начале). Значение метрики EIGRP становится значением cost community, что позволяет однозначно выбирать кратчайший маршрут.

Несмотря на то, что описанный подход неплохо работает с EIGRP в рамках L3VPN, у него есть очевидный побочный эффект – он изменяет стандартный и всем привычный алгоритм выбора лучшего пути. Как вы уже догадались, OSPF совершенно не в курсе про cost community, поэтому для его префиксов cуществует значение по умолчанию, 0x7FFFFFFF (214748347), которое значительно больше типовой метрики EIGRP.

На первый взгляд, можно было бы попробовать изменить метрику EIGRP таким образом, чтобы она была больше 0x7FFFFFFF. Однако это привело бы лишь к изменению «направления» проблемы, так как в этом случае уже R2 сравнивал бы значение по умолчанию для префиксов OSPF с огромной метрикой маршрутов EIGRP.

Самым простым решением, безусловно, было бы отключить добавление cost community в принципе, но увы, такой команды пока не существует. То, что доступно простым смертным – это игнорировать cost community в процессе выбора лучшего маршрута:

R1(config)#router bgp 123
R1(config-router)#bgp bestpath cost-community ignore 
R3#sho bgp vpnv4 unicast all 
BGP table version is 26, local router ID is 3.3.3.3
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, 
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, 
              x best-external, a additional-path, c RIB-compressed, 
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 1:1 (default for vrf A)
 *>i 4.4.4.4/32       1.1.1.1                  2    100      0 ?
 *>i 5.5.5.5/32       2.2.2.2             103040    100      0 ?
 *>  6.6.6.6/32       192.168.36.6             0             0 6 i
 * i 8.8.8.8/32       1.1.1.1                  2    100      0 ?
 *>i                  2.2.2.2             103040    100      0 ?
 *>i 192.168.14.0     1.1.1.1                  0    100      0 ?
 *>i 192.168.25.0     2.2.2.2                  0    100      0 ?

Хоть нам и удалось отвлечь R1 от cost community, R3 страдает тем же самым недугом: методично выбирает лучший маршрут от EIGRP, несмотря на все остальные атрибуты.

R3#sho bgp vpnv4 unicast all 
BGP table version is 29, local router ID is 3.3.3.3
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, 
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, 
              x best-external, a additional-path, c RIB-compressed, 
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 1:1 (default for vrf A)
 *>i 4.4.4.4/32       1.1.1.1                  2    100      0 ?
 *>i 5.5.5.5/32       2.2.2.2             103040    100      0 ?
 *>  6.6.6.6/32       192.168.36.6             0             0 6 i
 *>i 8.8.8.8/32       1.1.1.1                  2    100      0 ?
 * i                  2.2.2.2             103040    100      0 ?
 *>i 192.168.14.0     1.1.1.1                  0    100      0 ?
 *>i 192.168.25.0     2.2.2.2                  0    100      0 ?

Наконец, выбор лучшего маршрута соответствует привычным всем правилам: меньший MED решает исход гонки. В качестве альтернативы можно было бы вручную удалить противный cost community из исходящих обновлений:

R2(config)#ip extcommunity-list 100 permit pre-bestpath
R2(config)#route-map COSTCOMM
R2(config-route-map)#set extcomm-list 100 delete
R2(config)#router bgp 123
R2(config-router)#address-family vpnv4
R2(config-router-af)#neighbor L3VPN route-map COSTCOMM out 
R2#sho bgp vpnv4 unicast all extcommunity-list 100
BGP table version is 23, local router ID is 2.2.2.2
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, 
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter, 
              x best-external, a additional-path, c RIB-compressed, 
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 1:1 (default for vrf A)
 *>  5.5.5.5/32       192.168.25.5        103040         32768 ?
 *>  8.8.8.8/32       192.168.25.5        103040         32768 ?
 *>  192.168.25.0     0.0.0.0                  0         32768 ?
R3#sho bgp vpnv4 unicast all 8.8.8.8/32
BGP routing table entry for 1:1:8.8.8.8/32, version 46
Paths: (2 available, best #1, table A)
  Advertised to update-groups:
     1         
  Refresh Epoch 5
  Local
    1.1.1.1 (metric 2) from 1.1.1.1 (1.1.1.1)
      Origin incomplete, metric 2, localpref 100, valid, internal, best
      Extended Community: RT:1:1 OSPF DOMAIN ID:0x0005:0x000000020200 
        OSPF RT:0.0.0.0:2:0 OSPF ROUTER ID:192.168.14.1:0
      mpls labels in/out nolabel/23
  Refresh Epoch 1
  Local
    2.2.2.2 (metric 2) from 2.2.2.2 (2.2.2.2)
      Origin incomplete, metric 103040, localpref 100, valid, internal
      Extended Community: RT:1:1 0x8800:32768:0 0x8801:1:2560 
        0x8802:65281:25600 0x8803:65281:1500 0x8806:0:134744072
      mpls labels in/out nolabel/23

Цели этой статьи – обсудить cost community и немного попрактиковаться в отладке. Не забывайте: в технике и технологии нет другого волшебства, кроме значений по умолчанию.

Большая печенька за рецензию: Анастасии Куралёвой.

Комментарии (3)


  1. BjLomax
    15.06.2022 23:14

    Индусы научили так показывать конфигурацию? Почему нельзя просто в виде текста её сделать ....


    1. braonle Автор
      16.06.2022 01:09

      1. GritsanY
        16.06.2022 23:45

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