Il y a plus d'un an maintenant, je cherchais à expliquer ceci :
$ for i in `seq 1 254`; do echo -n ".$i:"; mtr -r -c1 89.234.141.$i | grep "8.|"; done
.1: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.7 17.7 17.7 17.7 0.0
.2: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.7 17.7 17.7 17.7 0.0
.3: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
.4: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
.5: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
.6: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.7 17.7 17.7 17.7 0.0
.7: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
.8: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.5 17.5 17.5 17.5 0.0
.9: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.9 17.9 17.9 17.9 0.0
.10: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
[…]
.50: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.5 17.5 17.5 17.5 0.0
.51: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
.52: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.7 17.7 17.7 17.7 0.0
.53: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.7 17.7 17.7 17.7 0.0
.54: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
.55: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
.56: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.7 17.7 17.7 17.7 0.0
.57: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
.58: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.7 17.7 17.7 17.7 0.0
.59: 8.|-- hwhost-1.arn-fai.net 0.0% 1 17.6 17.6 17.6 17.6 0.0
.60: 8.|-- hwhost-2.arn-fai.net 0.0% 1 17.8 17.8 17.8 17.8 0.0
[…]
Que constate-t-on ? Que le 8e saut d'un traceroute/mtr depuis un point de départ non communiqué et à destination de n'importe quelle adresse IPv4 d'ARN est l'un des deux routeurs de l'association. On pose l'hypothèse que le routage entre ce point non communiqué et ARN ne change pas durant l'exécution de la boucle (j'ai vérifié que c'était bien le cas). Pourtant BGP, le protocole de routage entre opérateurs réseaux repose sur un algorithme déterministe à état fini : à un même instant T, une seule route est proposée par BGP pour insertion dans la table de routage globale. Donc, si le routage entre la source et ARN ne change pas, on devrait toujours entrer dans le réseau d'ARN par le même routeur, celui qui a monté sa session BGP avec le transitaire en premier (c'est le 9e critère de l'algorithme BGP en cas d'égalité).
Vu qu'en interne ARN travaille uniquement avec des routes /32, on pourrait penser qu'en plus de notre /24, nous annonçons malencontreusement tous nos /32 à nos transitaires. Ceci expliquerait pourquoi le routeur Cogent sait où envoyer les paquets pour chaque adresse. Après double vérification, ce n'est pas le cas. On pourrait penser que nos sessions BGP passent leur temps à flapper (monter->tomber->monter->tomber->etc.) et que le routeur en face prend la route de la plus vieille session BGP à chaque fois, mais ce n'est pas le cas, nos sessions BGP sont stables.
À l'époque, je n'ai pas su trouver les bons mots clés pour obtenir une réponse sur un moteur de recherche donc j'ai laissé cette réflexion de côté. Très récemment, guerby m'annonce l'arrivée d'un deuxième port 10G chez le FAI associatif toulousain tetaneutral.net. Il m'explique que Cogent propose, au choix, une agrégation des ports au niveau 2 (protocole LACP normalisé et largement utilisé) ou deux ports séparés, avec des IP d'interconnexion différentes et une session BGP supplémentaire puisque Cogent active BGP multipath. Dans les deux cas, la charge serait répartie sur les 2 ports entre l'unique routeur de tetaneutral.net et l'unique routeur Cogent@Toulouse. Ça m'interpelle, je lui raconte le constat ci-dessus et il m'indique que c'est très probablement BGP multipath qui produit cet effet.
Derrière BGP multipath se cache Equal-Cost Multi-Path (ECMP), une norme qui décrit comment un même routeur peut transférer des paquets vers une destination donnée à travers plusieurs liens physiques. L'idée est de répartir la charge entre plusieurs liens physiques. Concrètement, cela signifie qu'il y a deux next-hop dans une même entrée d'une table de transfert (FIB). Les paquets sont envoyés sur un lien ou sur un autre en fonction du résultat d'une fonction de hachage qui porte sur l'interface réseau source, le numéro du protocole au-dessus d'IP, l'IP source et l'IP destination. Pour une explication détaillée de comment cela fonctionne sous Linux, je recommande la lecture de cette page : Equal Cost Multipath Load Sharing - Hardware ECMP - Cumulus Linux 3.2.1 - Cumulus Networks. Partant de là, tous les protocoles de routage peuvent proposer une route multi next-hop à l'export dans la table de routage globale. Exemple : le logiciel de routage BIRD implémente cela pour BGP, OSPF et RIP. Pour BGP, cela consiste à considérer égales les routes identiques qui parviennent jusqu'à l'étape 8 de l'algorithme (on ne compare donc pas l'ancienneté de la session ni le router-id).
Depuis sa version 1.6, le logiciel de routage BIRD implémente BGP multipath. Pour l'utiliser (ainsi qu'OSPF et RIP multipath), il suffit d'ajouter la directive merge paths
dans le protocole kernel. Comme on l'a vu, il faut également que le noyau implémente ECMP. C'est le cas pour Linux et le noyau packagé dans Debian est compilé avec l'option KiVaBien :
$ grep "CONFIG_IP_ROUTE_MULTIPATH" /boot/config-3.16.0-4-amd64
CONFIG_IP_ROUTE_MULTIPATH=y
Forcément, j'ai testé en reproduisant la topologie d'ARN (un routeur « transitaire » et deux routeurs internes à l'asso, « router1 » et « router2 »). Sur le routeur « transitaire », au sein de la CLI de BIRD, aucun changement n'est visible :
bird> sh route
198.19.0.0/24 via 198.18.0.2 on eth1 [bgp_router1 12:01:16] * (100) [AS64512i]
via 198.18.0.3 on eth1 [bgp_router2 12:01:22] (100) [AS64512i]
Mais la différence apparaît bien dans la table de routage globale :
$ ip r sh
198.19.0.0/24 proto bird
nexthop via 198.18.0.2 dev eth1 weight 1
nexthop via 198.18.0.3 dev eth1 weight 1
Un ping depuis la machine « transitaire » et un tcpdump sur chaque « router » permet de mettre en évidence que le noyau Linux de la machine « transitaire » répartie chaque message ICMP echo-request sur chaque routeur. Sur router1 :
12:06:32.915176 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 2, length 64
12:06:34.930501 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 4, length 64
12:06:36.946371 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 6, length 64
12:06:38.962698 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 8, length 64
12:06:40.979035 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 10, length 64
[…]
Sur router2 :
12:06:32.500424 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 1, length 64
12:06:34.514644 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 3, length 64
12:06:36.530591 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 5, length 64
12:06:38.546779 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 7, length 64
12:06:40.562058 IP 198.18.0.1 > 198.19.0.1: ICMP echo request, id 2206, seq 9, length 64
[…]
Même chose en UDP. En revanche, en TCP, Linux implémente l'algorithme proposé dans le RFC 2992 et prend aussi en compte le port destination comme entrée de la fonction de hachage. Cela signifie que chaque paquet d'une même connexion TCP passera toujours par le même lien c'est-à-dire que le routeur a une vision « par flot/connexion » au lieu de « par paquet ». Cela a pour objectif de ne pas mélanger des liens qui auraient une MTU ou une latence trop différente car cela aurait des effets curieux sur les connexions TCP. :P
Je retiens donc que Cogent active BGP multipath par défaut sur ses routeurs. En revanche, Interoute, autre transitaire d'ARN, ne le fait pas :
$ for i in `seq 1 254`; do echo -n ".$i:"; mtr -r -c1 -z -b -w 89.234.141.$i | grep "8. AS"; done
.1: 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 15.5 15.0 14.6 15.5 0.0
.2: 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 14.9 15.1 14.5 15.6 0.0
.3: 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 15.2 14.9 14.6 15.4 0.0
.4: 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 14.8 15.0 14.6 15.4 0.0
.5: 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 14.7 15.0 14.5 15.6 0.0
.6: 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 19.6 15.5 14.6 19.6 1.4
.7: 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 14.9 15.0 14.3 15.5 0.0
.8: 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 15.3 15.0 14.4 15.3 0.0
.9: 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 14.8 14.8 14.5 15.3 0.0
.10 8. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 10 15.3 14.9 14.4 15.4 0.0
[…]
Merci à Alarig pour la fourniture de ces mtr. :)
En effet, hwhost-1 est bien le routeur d'ARN qui a la plus vieille session BGP établie avec Interoute.
ÉDIT DU 02/05/2017 À 23H25 : Après une demande au support effectuée hier, Interoute a activé BGP multipath et nous envoie les paquets sur nos deux routeurs :
% mtr 89.234.141.1
[…] Packets Pings
Host Loss% Snt Last Avg Best Wrst StDev
1. 172.20.44.1 0.0% 16 0.3 0.3 0.2 0.5 0.0
2. ???
3. lag-107.ncren201.Rennes.francetelecom.net 86.7% 16 1.8 1.7 1.6 1.8 0.0
4. ae43-0.niidf301.Paris.francetelecom.net 0.0% 16 4.6 5.1 4.6 5.9 0.0
5. ae40-0.niidf302.Paris.francetelecom.net 0.0% 16 5.2 5.2 4.7 5.8 0.0
6. 193.252.137.78 0.0% 16 5.4 9.8 5.3 13.9 2.4
7. 21stcentury.GW.opentransit.net 0.0% 15 12.3 12.8 12.2 15.0 0.5
8. ae0-0.par-gar-score-2-re0.interoute.net 0.0% 15 5.9 5.8 5.1 7.2 0.4
9. hwhost-1.arn-fai.net 0.0% 15 14.9 14.6 14.2 15.3 0.0
10. hwhost-2.arn-fai.net 0.0% 15 14.4 14.6 14.0 15.3 0.0
11. vpn-end.arn-fai.net 0.0% 15 14.3 14.9 14.3 15.4 0.0
% for i in `seq 1 254`; do echo -n ".$i:"; mtr -r -c1 -z -b -w 89.234.141.$i | grep "9. AS"; done
.1: 9. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 1 14.8 14.8 14.8 14.8 0.0
.2: 9. AS60630 hwhost-2.arn-fai.net (89.234.141.132) 0.0% 1 15.7 15.7 15.7 15.7 0.0
.3: 9. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 1 14.3 14.3 14.3 14.3 0.0
.4: 9. AS60630 hwhost-2.arn-fai.net (89.234.141.132) 0.0% 1 14.9 14.9 14.9 14.9 0.0
.5: 9. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 1 14.9 14.9 14.9 14.9 0.0
.6: 9. AS60630 hwhost-2.arn-fai.net (89.234.141.132) 0.0% 1 14.8 14.8 14.8 14.8 0.0
.7: 9. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 1 15.0 15.0 15.0 15.0 0.0
.8: 9. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 1 14.4 14.4 14.4 14.4 0.0
.9: 9. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 1 14.5 14.5 14.5 14.5 0.0
.10: 9. AS60630 hwhost-1.arn-fai.net (89.234.141.131) 0.0% 1 15.0 15.0 15.0 15.0 0.0
[…]
FIN DE L'ÉDIT DU 02/05/2017.