Fat-tree topology

Unequal Cost Multi-Path

Bernardo Soares
TechRebels
Published in
16 min readDec 10, 2018

--

Hoje vamos falar um pouco sobre FIB Hashing, e iremos implementar UCMP utilizando BGP.

Aproveite e fique ligado na TechRebels e siga-me no Medium clicando follow lá em cima para acompanhar os próximos posts.

O multipathing nos permite instalar simultaneamente diversas rotas para o mesmo destino na tabela de roteamento, com o objetivo de distribuir o tráfego entre diversos next-hops. Após aprender a rota e instalar o prefixo na RIB e FIB, vem a parte mais importante: Como o tráfego de trânsito é distribuído entre os caminhos/next-hops?

Existe suporte a multipath em todos os protocolos de roteamento (isso mesmo, static, ospf2/3, isis, eigrp, bgp, etc), desde que a métrica do protocolo seja a mesma para todas as entradas, e as entradas devem ser idênticas. Isso mesmo. Para se instalar vários caminhos a um prefixo X, todos os atributos devem ser idênticos (com exceção do next-hop, é claro) para que sejam todas consideradas iguais, e inseridas na tabela. Obviamente, os prefixos devem ter sido aprendidos pelo mesmo protocolo de roteamento.

Alguns routers fazem a distribuição per-packet. Isso é, ele distribui os pacotes um a um de maneira igual entre os next-hops. Isso é conhecido também como round-robin.

Este método possui algumas desvantagens, pois a distribuição não é determinística. Isso quer dizer que pacotes do mesmo fluxo não necessariamente serão encaminhados pelo mesmo caminho, causando assimetria no tráfego.

Alguns comportamentos bem conhecidos e comuns são causados por esta assimetria, como a chegada dos pacotes fora de ordem e perda de state (caso exista(m) firewalls ou NAT no caminho).

No entanto, o tópico de hoje tem a ver com um outro tipo de distribuição de tráfego, que utiliza o que chamamos de FIB Hashing.

O FIB hashing consiste em avaliar o cabeçalho do pacote e associá-lo à uma determinada entrada na FIB — o que faz com que um mesmo fluxo sempre seja associado com a mesma entrada. Isso ocorre pois um fluxo é categorizado por [src_ip + dst_ip + src_port + dst_port] — resultando sempre no mesmo hash. (Apesar do exemplo acima, as “tuples” são geralmente configuráveis)

A maneira exata como a decisão de forwarding é tomada depende da plataforma, onde vários fatores tais como arquitetura de linecards e FIB variam de plataforma para plataforma.

Por default, quando existem mais de uma rota para o mesmo destino, a maioria dos equipamentos implementa o que chamamos de “ECMP”, ou Equal Cost Multi Path.

Com o ECMP, os fluxos (e não pacotes!!) serão distribuídos igualmente entre os next-hop, ocasionando em um comportamento determinístico durante o caminho entre o source e o destination (bem, assumindo que todos no caminho fazem este tipo de hashing). Em outras palavras, o mesmo flow sempre gerará o mesmo resultado hash, o que será sempre associado à mesma interface (ou next-hop, ou FIB entry).

Algumas implementações nos permitem influenciar este hashing — nos dando mais controle sobre como o tráfego é encaminhado para um determinado destino. Podendo influenciar este hashing, conseguimos implementar o que é conhecido como UCMP -Unequal Cost Multi Path.

Atualmente, EIGRP e BGP suportam UCMP. O EIGRP o faz com a feature conhecida como “variance”. Porem, o foco de hoje sera na implementação de UCMP via BGP, utilizando a community extended “Link BW Community”.

Link BW Community

Especificado inicialmente em 2009 pelo draft “ draft-rfernando-idr-link-bandwidth-00 “, a community Link Bandwidth é uma extended community Optional Non-transitive ( Valor 0x4004 ), e foi especificada com o intuito de sinalizar internamente ( aos peers iBGP ) as características de um link externo ( onde ocorre o peering eBGP ). Desta forma, os routers internos podem tomar uma decisão de roteamento mais específica. E, quando utilizado junto com a feature “multipath”, resulta em UCMP.

Até então, o uso desta community se dava principalmente em casos de peering em WANs, onde o uso de links de menor capacidade eram a única opção.

Por um bom tempo, o suporte desta feature em equipamentos Cisco (IOS) se restringia ao valor de BW da interface em que o peering é estabelecido:

Configuração básica (usando links de capacidades distintas):

Exemplo DMZ BW considerando links de capacidades diferentes
##Edge1Edge1#sh run | sec bgp
router bgp 65000
bgp log-neighbor-changes
bgp dmzlink-bw
neighbor 10.0.0.0 remote-as 100
neighbor 10.0.0.0 dmzlink-bw
neighbor 10.10.10.10 remote-as 65000
neighbor 10.10.10.10 update-source Loopback0
neighbor 10.10.10.10 next-hop-self
neighbor 10.10.10.10 send-community both
Edge1#sh run int e0/1
Building configuration…
Current configuration : 79 bytes
!
interface Ethernet0/1
ip address 10.0.0.1 255.255.255.254
duplex auto
end
Edge1#sh ip b 8.8.8.8
BGP routing table entry for 8.8.8.8/32, version 2
Paths: (1 available, best #1, table default)
Advertised to update-groups:
2
Refresh Epoch 1
100
10.0.0.0 from 10.0.0.0 (8.8.8.8)
Origin IGP, metric 0, localpref 100, valid, external, best
DMZ-Link Bw 1250 kbytes
rx pathid: 0, tx pathid: 0x0
Edge1#sh int e0/1
Ethernet0/1 is up, line protocol is up
Hardware is AmdP2, address is aabb.cc00.8110 (bia aabb.cc00.8110)
Internet address is 10.0.0.1/31
MTU 1500 bytes, BW 10000 Kbit/sec, DLY 1000 usec,
###Edge2Edge2#sh run | sec bgp
router bgp 65000
bgp log-neighbor-changes
bgp dmzlink-bw
neighbor 10.0.1.0 remote-as 100
neighbor 10.0.1.0 dmzlink-bw
neighbor 10.10.10.10 remote-as 65000
neighbor 10.10.10.10 update-source Loopback0
neighbor 10.10.10.10 next-hop-self
neighbor 10.10.10.10 send-community both
Edge2# sh run int e0/1
Building configuration…
Current configuration : 95 bytes
!
interface Ethernet0/1
bandwidth 2000
ip address 10.0.1.1 255.255.255.254
duplex auto
end
Edge2#sh ip bgp 8.8.8.8
BGP routing table entry for 8.8.8.8/32, version 4
Paths: (1 available, best #1, table default)
Advertised to update-groups:
2
Refresh Epoch 3
100
10.0.1.0 from 10.0.1.0 (8.8.8.8)
Origin IGP, metric 0, localpref 100, valid, external, best
DMZ-Link Bw 250 kbytes
rx pathid: 0, tx pathid: 0x0
Edge2#sh int e0/1
Ethernet0/1 is up, line protocol is up
Hardware is AmdP2, address is aabb.cc00.7110 (bia aabb.cc00.7110)
Internet address is 10.0.1.1/31
MTU 1500 bytes, BW 2000 Kbit/sec, DLY 1000 usec,

###Core
CORE#sh run | sec bgp
router bgp 65000
bgp log-neighbor-changes
bgp dmzlink-bw
neighbor IBGP peer-group
neighbor IBGP remote-as 65000
neighbor IBGP update-source Loopback0
neighbor IBGP next-hop-self
neighbor 1.1.1.1 peer-group IBGP
neighbor 2.2.2.2 peer-group IBGP
maximum-paths eibgp 20
CORE#sh ip b 8.8.8.8
BGP routing table entry for 8.8.8.8/32, version 6
Paths: (2 available, best #1, table default)
Multipath: eiBGP
Not advertised to any peer
Refresh Epoch 1
100
2.2.2.2 (metric 11) from 2.2.2.2 (2.2.2.2)
Origin IGP, metric 0, localpref 100, valid, internal, multipath, best
DMZ-Link Bw 250 kbytes
rx pathid: 0, tx pathid: 0x0
Refresh Epoch 1
100
1.1.1.1 (metric 11) from 1.1.1.1 (172.16.50.1)
Origin IGP, metric 0, localpref 100, valid, internal, multipath(oldest)
DMZ-Link Bw 1250 kbytes
rx pathid: 0, tx pathid: 0
CORE#sh ip route 8.8.8.8
Routing entry for 8.8.8.8/32
Known via “bgp 65000”, distance 200, metric 0
Tag 100, type internal
Last update from 2.2.2.2 00:00:13 ago
Routing Descriptor Blocks:
2.2.2.2, from 2.2.2.2, 00:00:13 ago
Route metric is 0, traffic share count is 1
AS Hops 1
Route tag 100
MPLS label: none
* 1.1.1.1, from 1.1.1.1, 00:00:13 ago
Route metric is 0, traffic share count is 5
AS Hops 1
Route tag 100
MPLS label: none

No exemplo acima, temos dois links em dois routers distintos, Edge1 possui um link de 10Mb e Edge2 possui um link de 2Mb. Ao configurar a feature de DMZ-Link BW, estes valores sao associados ao prefixo recebido do next-hop (8.8.8.8, no caso) em bytes/s.

Em seguida, validamos a tabela de roteamento, indicando uma distribuição de 5/1.

Em algumas plataformas (IOS-XR, Junos), este valor pode ser configurado manualmente. Com esta flexibilidade, podemos distribuir o fluxo de dados de uma forma bem granular.

Porém, vamos pensar no seguinte cenário. Temos aqui 4 servidores, que fornecem o mesmo serviço (NTP, DNS, etc. UDP, para simplificar). Num cenário ideal, gostaríamos sempre de ter nosso setup de uma maneira homogênea, com todos os dispositivos com capacidade semelhante e operacionalmente idênticos.

Não é bem o que acontece no mundo real, não é?

Então, vamos supor que, destes 4 servidores, o SERVER4 e SERVER2 são inferiores, com a metade da memória. Com o comportamento ECMP, todos os 4 servidores receberão aproximadamente a mesma carga. Eventualmente, os de capacidade inferior chegarão próximo do limite — o que pode degradar o tempo de resposta — ou até mesmo interferir no funcionamento do sistema operacional (que pode ou não hospedar outras aplicações — piorando o efeito).

Neste caso, podemos empregar o conceito de UCMP.

Para exemplificar o cenário, usarei a seguinte topologia:

Nossos IOS-XR e Junos atuarão como “Spine”, e teremos quatro routers IOS simulando “servidores”, ou até mesmo “Leaf” switches. A lógica que usaremos é a seguinte:

Caso o prefixo possua uma determinada community standard, utilizamos uma route-policy para transforma-la na community LB. Caso não haja nenhuma community (ou qualquer outro valor que não sejam os configurados explicitamente), associamos um valor mínimo:

LB_STD_16 --> LB_EXT_16 -->  64512:16000
LB_STD_32 --> LB_EXT_32 --> 64512:32000
LB_STD_64 --> LB_EXT_64 --> 64512:64000
ANY . --> LB_EXT_MIN -> 64512:8000

Voltando ao exemplo anterior, estes serão os valores que vamos configurar:

SERVER1 -->  64512:32000
SERVER2 --> 64512:16000
SERVER3 --> 64512:32000
SERVER4 --> 64512:16000

Agora as configurações básicas:

###Servidor:hostname Server4
!
interface Loopback0
ip address 4.4.4.4 255.255.255.255
ip ospf 1 area 0
!
interface Loopback1
description Anycast
ip address 172.16.10.1 255.255.255.255
!
interface Ethernet0/0
ip address 10.0.0.6 255.255.255.254
ip ospf network point-to-point
ip ospf 1 area 0
!
interface Ethernet0/1
ip address 10.0.1.6 255.255.255.254
ip ospf network point-to-point
ip ospf 1 area 0
!
router ospf 1
router-id 4.4.4.4
prefix-suppression
passive-interface Loopback0
!
router bgp 64512
neighbor SPINE peer-group
neighbor SPINE remote-as 64512
neighbor SPINE update-source Loopback0
neighbor 10.10.10.10 peer-group SPINE
neighbor 20.20.20.20 peer-group SPINE
!
address-family ipv4
network 172.16.10.1 mask 255.255.255.255
neighbor SPINE send-community
neighbor SPINE next-hop-self
neighbor 10.10.10.10 activate
neighbor 20.20.20.20 activate
exit-address-family
!###Spine (XR):hostname SPINE1
interface Loopback0
ipv4 address 10.10.10.10 255.255.255.255
!
interface GigabitEthernet0/0/0/0
ipv4 address 10.0.0.1 255.255.255.254
!
interface GigabitEthernet0/0/0/1
ipv4 address 10.0.0.3 255.255.255.254
!
interface GigabitEthernet0/0/0/2
ipv4 address 10.0.0.5 255.255.255.254
!
interface GigabitEthernet0/0/0/3
ipv4 address 10.0.0.7 255.255.255.254
!
prefix-set HOST_ROUTES
0.0.0.0/0 eq 32
end-set
!
route-policy ANYCAST_IN
if destination in HOST_ROUTES then
done
else
drop
endif
end-policy
!
router ospf 1
address-family ipv4
area 0
interface Loopback0
!
interface GigabitEthernet0/0/0/0
network point-to-point
!
interface GigabitEthernet0/0/0/1
network point-to-point
!
interface GigabitEthernet0/0/0/2
network point-to-point
!
interface GigabitEthernet0/0/0/3
network point-to-point
!
!
!
router bgp 64512
bgp router-id 10.10.10.10
address-family ipv4 unicast
maximum-paths ibgp 4
!
neighbor-group IBGP
remote-as 64512
update-source Loopback0
address-family ipv4 unicast
route-policy ANYCAST_IN in
!
!
neighbor 1.1.1.1
use neighbor-group IBGP
!
neighbor 2.2.2.2
use neighbor-group IBGP
!
neighbor 3.3.3.3
use neighbor-group IBGP
!
neighbor 4.4.4.4
use neighbor-group IBGP
!
###Spine (Junos)
Nota: !!! NUNCA usem "bgp allow 0.0.0.0/0" em um router em produção!!!!
set interfaces ge-0/0/0 unit 0 family inet address 10.0.1.1/31
set interfaces ge-0/0/1 unit 0 family inet address 10.0.1.3/31
set interfaces ge-0/0/2 unit 0 family inet address 10.0.1.5/31
set interfaces ge-0/0/3 unit 0 family inet address 10.0.1.7/31
set interfaces lo0 unit 0 family inet address 20.20.20.20/32
set routing-options router-id 20.20.20.20
set routing-options autonomous-system 64512
set protocols bgp group IBGP local-address 20.20.20.20
set protocols bgp group IBGP multipath
set protocols bgp group IBGP import ANYCAST_INset protocols bgp group IBGP family inet unicast local-ipv4-address 20.20.20.20
set protocols bgp group IBGP peer-as 64512
set protocols bgp group IBGP allow 0.0.0.0/0
set protocols ospf area 0.0.0.0 interface ge-0/0/0.0 interface-type p2p
set protocols ospf area 0.0.0.0 interface ge-0/0/1.0 interface-type p2p
set protocols ospf area 0.0.0.0 interface ge-0/0/2.0 interface-type p2p
set protocols ospf area 0.0.0.0 interface ge-0/0/3.0 interface-type p2p
set protocols ospf area 0.0.0.0 interface lo0.0 metric 1
set policy-options policy-statement ANYCAST_IN term ALLOW from source-address-filter 172.16.10.1/32 exact
set policy-options policy-statement ANYCAST_IN term ALLOW then accept
set policy-options policy-statement ANYCAST_IN term DROP then reject

Agora vamos ver a tabela de roteamento. Vemos o prefixo 172.16.10.1/32 através de 4 diferentes next-hops. Em destaque, podemos ver a distribuição entre os next-hops:

### IOS-XR (Sem Community):RP/0/0/CPU0:SPINE1#     sh bgp 172.16.10.1
Wed Nov 21 10:52:26.466 UTC
BGP routing table entry for 172.16.10.1/32
Versions:
Process bRIB/RIB SendTblVer
Speaker 22 22
Last Modified: Nov 21 10:50:30.583 for 00:01:55
Paths: (4 available, best #1)
Not advertised to any peer
Path #1: Received by speaker 0
Not advertised to any peer
Local
1.1.1.1 (metric 2) from 1.1.1.1 (172.16.10.1)
Origin IGP, metric 0, localpref 100, valid, internal, best, group-best, multipath
Received Path ID 0, Local Path ID 1, version 22
Path #2: Received by speaker 0
Not advertised to any peer
Local
2.2.2.2 (metric 2) from 2.2.2.2 (172.16.10.1)
Origin IGP, metric 0, localpref 100, valid, internal, multipath
Received Path ID 0, Local Path ID 0, version 0
Path #3: Received by speaker 0
Not advertised to any peer
Local
3.3.3.3 (metric 2) from 3.3.3.3 (172.16.10.1)
Origin IGP, metric 0, localpref 100, valid, internal, multipath
Received Path ID 0, Local Path ID 0, version 0
Path #4: Received by speaker 0
Not advertised to any peer
Local
4.4.4.4 (metric 2) from 4.4.4.4 (172.16.10.1)
Origin IGP, metric 0, localpref 100, valid, internal, multipath
Received Path ID 0, Local Path ID 0, version 0
RP/0/0/CPU0:SPINE1# show cef ipv4 172.16.10.1 det
Wed Nov 21 10:53:02.903 UTC
172.16.10.1/32, version 94, internal 0x5000001 0x0 (ptr 0xa13f1ef4) [1], 0x0 (0x0), 0x0 (0x0)
<snip>Load distribution: 0 1 2 3 (refcount 1)Hash OK Interface Address
0 Y GigabitEthernet0/0/0/0 10.0.0.0
1 Y GigabitEthernet0/0/0/1 10.0.0.2
2 Y GigabitEthernet0/0/0/2 10.0.0.4
3 Y GigabitEthernet0/0/0/3 10.0.0.6
###Junos (Sem community):@SPINE2> show route 172.16.10.1/32inet.0: 20 destinations, 23 routes (20 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.10.1/32 *[BGP/170] 00:01:11, MED 0, localpref 100, from 1.1.1.1
AS path: I, validation-state: unverified
> to 10.0.1.0 via ge-0/0/0.0
[BGP/170] 00:01:11, MED 0, localpref 100, from 2.2.2.2
AS path: I, validation-state: unverified
> to 10.0.1.2 via ge-0/0/1.0
[BGP/170] 00:01:11, MED 0, localpref 100, from 3.3.3.3
AS path: I, validation-state: unverified
> to 10.0.1.4 via ge-0/0/2.0
[BGP/170] 00:01:11, MED 0, localpref 100, from 4.4.4.4
AS path: I, validation-state: unverified
> to 10.0.1.6 via ge-0/0/3.0
@SPINE2# run show route 172.16.10.1 detailinet.0: 20 destinations, 23 routes (20 active, 0 holddown, 0 hidden)
172.16.10.1/32 (4 entries, 1 announced)
*BGP Preference: 170/-101
Next hop type: Indirect, Next hop index: 0
Address: 0xcb68130
Next-hop reference count: 2
Source: 1.1.1.1
Next hop type: Router, Next hop index: 560
Next hop: 10.0.1.0 via ge-0/0/0.0, selected
Session Id: 0x0
Protocol next hop: 1.1.1.1
Indirect next hop: 0xb31a400 262142 INH Session ID: 0x0
State: <Active Int Ext>
Local AS: 64512 Peer AS: 64512
Age: 1:43 Metric: 0 Metric2: 2
Validation State: unverified
Task: BGP_64512.1.1.1.1+54924
Announcement bits (2): 0-KRT 4-Resolve tree 1
AS path: I
Accepted
Localpref: 100
Router ID: 172.16.10.1

Agora, após aplicar a policy para inserir a community nos prefixos, vamos verificar para ver o que mudou:

#### IOS-XR (community default):extcommunity-set bandwidth LB_EXT_16
64512:16000
end-set
!
extcommunity-set bandwidth LB_EXT_32
64512:32000
end-set
!
extcommunity-set bandwidth LB_EXT_64
64512:64000
end-set
!
extcommunity-set bandwidth LB_EXT_MIN
64512:8000
end-set
!
community-set LB_STD_16
64512:16000
end-set
!
community-set LB_STD_32
64512:32000
end-set
!
community-set LB_STD_64
64512:64000
end-set
!
route-policy UNEQUAL_LB
if community matches-any LB_STD_16 then
set extcommunity bandwidth LB_EXT_16 additive
elseif community matches-any LB_STD_32 then
set extcommunity bandwidth LB_EXT_32 additive
elseif community matches-any LB_STD_64 then
set extcommunity bandwidth LB_EXT_64 additive
else
set extcommunity bandwidth LB_EXT_MIN additive
endif
end-policy
!
route-policy ANYCAST_IN
apply UNEQUAL_LB
if destination in HOST_ROUTES then
done
else
drop
endif
end-policy
!
##VerificandoRP/0/0/CPU0:SPINE1# sh bgp 172.16.10.1
Wed Nov 21 10:31:03.304 UTC
BGP routing table entry for 172.16.10.1/32
Versions:
Process bRIB/RIB SendTblVer
Speaker 13 13
Last Modified: Nov 21 10:30:50.583 for 00:00:12
Paths: (4 available, best #1)
Not advertised to any peer
Path #1: Received by speaker 0
Not advertised to any peer
Local
1.1.1.1 (metric 2) from 1.1.1.1 (172.16.10.1)
Origin IGP, metric 0, localpref 100, valid, internal, best, group-best, multipath
Received Path ID 0, Local Path ID 1, version 13
Extended community: LB:64512:64
Path #2: Received by speaker 0
Not advertised to any peer
Local
2.2.2.2 (metric 2) from 2.2.2.2 (172.16.10.1)
Origin IGP, metric 0, localpref 100, valid, internal, multipath
Received Path ID 0, Local Path ID 0, version 0
Extended community: LB:64512:64
Path #3: Received by speaker 0
Not advertised to any peer
Local
3.3.3.3 (metric 2) from 3.3.3.3 (172.16.10.1)
Origin IGP, metric 0, localpref 100, valid, internal, multipath
Received Path ID 0, Local Path ID 0, version 0
Extended community: LB:64512:64
Path #4: Received by speaker 0
Not advertised to any peer
Local
4.4.4.4 (metric 2) from 4.4.4.4 (172.16.10.1)
Origin IGP, metric 0, localpref 100, valid, internal, multipath
Received Path ID 0, Local Path ID 0, version 0
Extended community: LB:64512:64
RP/0/0/CPU0:SPINE1#sh cef ipv4 172.16.10.1 det
Wed Nov 21 10:31:14.823 UTC
172.16.10.1/32, version 70, internal 0x5000001 0x0 (ptr 0xa13f21f4)
<snip>Weight distribution:
slot 0, weight 64, normalized_weight 1, class 0
slot 1, weight 64, normalized_weight 1, class 0
slot 2, weight 64, normalized_weight 1, class 0
slot 3, weight 64, normalized_weight 1, class 0
Load distribution: 0 1 2 3 (refcount 1)Hash OK Interface Address
0 Y GigabitEthernet0/0/0/0 10.0.0.0
1 Y GigabitEthernet0/0/0/1 10.0.0.2
2 Y GigabitEthernet0/0/0/2 10.0.0.4
3 Y GigabitEthernet0/0/0/3 10.0.0.6
###Junos (Community default)set policy-options policy-statement UCMP term BW_64 from community LB_STD_64
set policy-options policy-statement UCMP term BW_64 then community set LB_EXT_64
set policy-options policy-statement UCMP term BW_64 then next policy
set policy-options policy-statement UCMP term BW_32 from community LB_STD_32
set policy-options policy-statement UCMP term BW_32 then community set LB_EXT_32
set policy-options policy-statement UCMP term BW_32 then next policy
set policy-options policy-statement UCMP term BW_16 from community LB_STD_16
set policy-options policy-statement UCMP term BW_16 then community set LB_EXT_16
set policy-options policy-statement UCMP term BW_16 then next policy
set policy-options policy-statement UCMP term DEFAULT then community set LB_EXT_MIN
set policy-options community LB_EXT_16 members bandwidth:64512:16000
set policy-options community LB_EXT_32 members bandwidth:64512:32000
set policy-options community LB_EXT_64 members bandwidth:64512:64000
set policy-options community LB_EXT_MIN members bandwidth:64512:8000
set policy-options community LB_STD_16 members 64512:16000
set policy-options community LB_STD_32 members 64512:32000
set policy-options community LB_STD_64 members 64512:64000
set protocols bgp group IBGP import UCMP
set protocols bgp group IBGP import ANYCAST_IN
##Verificando@SPINE2> show route 172.16.10.1 detailinet.0: 20 destinations, 23 routes (20 active, 0 holddown, 0 hidden)
172.16.10.1/32 (4 entries, 1 announced)
*BGP Preference: 170/-101
Next hop type: Indirect, Next hop index: 0
Address: 0xb779ef0
Next-hop reference count: 2
Source: 1.1.1.1
Next hop type: Router, Next hop index: 560
Next hop: 10.0.1.0 via ge-0/0/0.0
Session Id: 0x0
Next hop type: Router, Next hop index: 561
Next hop: 10.0.1.2 via ge-0/0/1.0, selected
Session Id: 0x0
Next hop type: Router, Next hop index: 562
Next hop: 10.0.1.4 via ge-0/0/2.0
Session Id: 0x0
Next hop type: Router, Next hop index: 563
Next hop: 10.0.1.6 via ge-0/0/3.0
Session Id: 0x0
Protocol next hop: 1.1.1.1 Balance: 25%
Indirect next hop: 0xb31a400 262142 INH Session ID: 0x0
Protocol next hop: 2.2.2.2 Balance: 25%
Indirect next hop: 0xb31a280 262143 INH Session ID: 0x0
Protocol next hop: 3.3.3.3 Balance: 25%
Indirect next hop: 0xb31a880 - INH Session ID: 0x0
Protocol next hop: 4.4.4.4 Balance: 25%
Indirect next hop: 0xb31ad00 - INH Session ID: 0x0
State: <Active Int Ext>
Local AS: 64512 Peer AS: 64512
Age: 9 Metric: 0 Metric2: 2
Validation State: unverified
Task: BGP_64512.1.1.1.1+54924
Announcement bits (3): 0-KRT 4-Resolve tree 1 6-BGP_Listen.0.0.0.0+179
AS path: I
Communities: bandwidth:64512:8000
Accepted Multipath
Localpref: 100
Router ID: 172.16.10.1
<snip>

Agora, em itálico, vemos a distribuição de carga entre os caminhos. Neste exemplo ainda temos os valores idênticos, resultando em ECMP. Repare que, no IOS-XR, o valor configurado é em bytes/s, e o weight nos mostra em kilobits/s . Diferentemente, o Junos nos retorna a porcentagem de carga associada a cada entrada, conforme exemplo acima.

Nota: Com a community de LB, o comportamento de load sharing so é alterado caso todos os prefixos tenham um valor de LB community. Caso algum caminho não tenha esta community, os valores são ignorados e o ECMP é utilizado.

Agora vamos associar o valor de communities da seguinte maneira:

SERVER1 -->  64512:32000
SERVER2 --> 64512:16000
SERVER3 --> 64512:32000
SERVER4 --> 64512:16000

Enviando a community aos SPINE:

###Server1:ip bgp-community new-format
!
route-map LB_STD permit 5
set community 64512:32000
!
router bgp 64512
address-family ipv4
network 172.16.10.1 mask 255.255.255.255 route-map LB_STD
###Server2ip bgp-community new-format
!
route-map LB_STD permit 5
set community 64512:16000
!
router bgp 64512
address-family ipv4
neighbor SPINE route-map LB_STD out
###Server3ip bgp-community new-format
!
route-map LB_STD permit 5
set community 64512:32000
!
router bgp 64512
address-family ipv4
neighbor SPINE route-map LB_STD out
##Server4ip bgp-community new-format
!
route-map LB_STD permit 5
set community 64512:16000
!
router bgp 64512
address-family ipv4
network 172.16.10.1 mask 255.255.255.255 route-map LB_STD

Verificando se recebemos este valor de community:

###IOS-XRRP/0/0/CPU0:SPINE1#sh bgp ipv4 u 172.16.10.1 | i "from|mmuni"
Wed Dec 5 10:03:51.611 UTC
1.1.1.1 (metric 2) from 1.1.1.1 (172.16.10.1)
Community: 64512:32000
Extended community: LB:64512:256
2.2.2.2 (metric 2) from 2.2.2.2 (172.16.10.1)
Community: 64512:16000
Extended community: LB:64512:128
3.3.3.3 (metric 2) from 3.3.3.3 (172.16.10.1)
Community: 64512:32000
Extended community: LB:64512:256
4.4.4.4 (metric 2) from 4.4.4.4 (172.16.10.1)
Community: 64512:16000
Extended community: LB:64512:128
RP/0/0/CPU0:SPINE1#show cef ipv4 172.16.10.1 det | i "via|idx|eight|Interface|$
Wed Dec 5 10:07:05.747 UTC
via 1.1.1.1/32, 2 dependencies, recursive, bgp-multipath [flags 0x6080]
path-idx 0 NHID 0x0 [0xa13f1d74 0x0]
next hop 1.1.1.1/32 via 1.1.1.1/32
via 2.2.2.2/32, 2 dependencies, recursive, bgp-multipath [flags 0x6080]
path-idx 1 NHID 0x0 [0xa13f1df4 0x0]
next hop 2.2.2.2/32 via 2.2.2.2/32
via 3.3.3.3/32, 2 dependencies, recursive, bgp-multipath [flags 0x6080]
path-idx 2 NHID 0x0 [0xa13f1e74 0x0]
next hop 3.3.3.3/32 via 3.3.3.3/32
via 4.4.4.4/32, 2 dependencies, recursive, bgp-multipath [flags 0x6080]
path-idx 3 NHID 0x0 [0xa13f1cf4 0x0]
next hop 4.4.4.4/32 via 4.4.4.4/32
Weight distribution:
slot 0, weight 256, normalized_weight 2, class 0
slot 1, weight 128, normalized_weight 1, class 0
slot 2, weight 256, normalized_weight 2, class 0
slot 3, weight 128, normalized_weight 1, class 0
Load distribution: 0 0 1 2 2 3 (refcount 1) Hash OK Interface Address
0 Y GigabitEthernet0/0/0/0 10.0.0.0
1 Y GigabitEthernet0/0/0/0 10.0.0.0
2 Y GigabitEthernet0/0/0/1 10.0.0.2
3 Y GigabitEthernet0/0/0/2 10.0.0.4
4 Y GigabitEthernet0/0/0/2 10.0.0.4
5 Y GigabitEthernet0/0/0/3 10.0.0.6
###Junos@SPINE2> ...2.16.10.1 detail | match "source|comm" | except Inac
Source: 1.1.1.1
Communities: bandwidth:64512:32000
Source: 2.2.2.2
Communities: bandwidth:64512:16000
Source: 3.3.3.3
Communities: bandwidth:64512:32000
Source: 4.4.4.4
Communities: bandwidth:64512:16000
@SPINE2> show route 172.16.10.1 detail | match "Protocol next"
Protocol next hop: 1.1.1.1 Balance: 33%
Protocol next hop: 2.2.2.2 Balance: 17%
Protocol next hop: 3.3.3.3 Balance: 33%
Protocol next hop: 4.4.4.4 Balance: 17%

Como podemos ver, ambas as plataformas nos mostram a distribuição entre os next-hop “desiguais”. Com esta configuração, o resultado é que, os servidores 2 e 4 receberão cada um aproximadamente 50% dos fluxos recebidos pelos de número 1 e 3. Da mesma maneira, caso desejamos novamente alterar esta distribuição, basta alterar o valor da community standard anunciado pelo próprio servidor. Bem fácil, né?

Conclusão

Nesse post, abordamos brevemente os conceitos de FIB Hashing e Multipathing; com foco em Unequal Cost Multipath em BGP através da Community de link BW. Também demonstramos dois casos de uso para tal feature:

  • Distribuição de carga em links de capacidades diferentes (eBGP)
  • UCMP no “fabric” do Data Center, permitindo distribuição de carga desigual para servidores usando Anycast (usando iBGP).

Seguem mais referências sobre o tema:

https://tools.ietf.org/html/draft-ietf-idr-link-bandwidth-07

https://tools.ietf.org/html/rfc4360

https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/iproute_bgp/configuration/xe-16/irg-xe-16-book/bgp-link-bandwidth.html

https://www.juniper.net/documentation/en_US/junos/topics/example/bgp-multipath-unequal.html

Se gostou do conteúdo, peço para compartilhar com outros do ramo. Não se esqueça de seguir a mim e ao TechRebels clicando follow aí embaixo :)

Sobre o autor:

Bernardo, CCIE #57862

Cloud Network Engineer

linkedin.com/in/bernardosoares/

--

--

TechRebels
TechRebels

Published in TechRebels

The day-to-day of the IT Infrastructure. Higher quality content and less filter :P

Bernardo Soares
Bernardo Soares