http://www.bortzmeyer.org/6956.html
----------------------------
Auteur(s) du RFC: W. Wang (Zhejiang Gongshang University), E. Haleplidis
(University of Patras), K. Ogawa (NTT Corporation), C. Li (Hangzhou DPtech), J.
Halpern (Ericsson)
Chemin des normes
----------------------------
Le protocole ForCES vise à permettre la création d'équipements réseaux
(par exemple des routeurs) en assemblant des pièces d'origines
diverses, parlant un protocole commun et pouvant donc interagir. Ce RFC
marque l'achèvement de la première (et très longue) phase de ForCES, la
normalisation complète de ce protocole. Notre RFC 6956 décrit la
bibliothèque standard de ForCES, les parties d'un routeur qu'on
trouvera partout et qui assurent les fonctions indispensables comme
faire suivre un paquet IP.
ForCES peut servir à bien d'autres choses et il y aura aussi des
bibliothèques pour d'autres équipements que les routeurs, et aussi des
bibliothèques non-standard, développées par tel ou tel projet. Mais
pour atteindre l'objectif premier de ForCES, créer un routeur par
assemblage de pièces standards, cette bibliothèque « routeur » était le
dernier élement manquant.
Avant de lire ce RFC 6956, il faut bien se pénétrer du cadre général
(RFC 3746), du protocole (RFC 5810) et du modèle de données (RFC 5812).
J'en extrais quelques termes qu'il faut connaître :
* NE ou "Network Element", l'engin complet (un routeur, un commutateur,
etc).
* CE ou "Control Element", la partie du NE qui fait tourner les
protocoles de contrôle et de signalisation (pour un routeur, OSPF, BGP,
etc).
* FE ou "Forwarding Element", la partie de l'engin qui traite les
paquets (pour un routeur, qui les fait suivre d'une interface à
l'autre). CE et FE se parlent en suivant le protocole ForCES. Un NE
comprend au moins un CE et un FE.
* LFB ou "Logical Function Block", c'est le concept qui fait l'objet de
ce RFC. Un LFB est une fonction d'un FE, contrôlée par le CE. Un FE
typique met en œuvre plusieurs fonctions (par exemple : faire suivre
les paquets, filtrer les paquets, compter les paquets et chacune de ces
trois fonctions est représentée par un LFB). Un CE typique va donc
utiliser le protocole ForCES pour configurer les LFB (« arrête de faire
suivre les paquets », « coupe l'interface Ethernet/0/2 », etc). Un LFB
est une fonction logique : dans la matériel, on ne retrouve pas
forcément ce concept.
* Classe de LFB et instance de LFB sont des concepts empruntés à la
programmation objet. L'idée est qu'on définit des classes de LFB et que
le LFB dans un FE donné est une instance d'une de ces classes.
* Un « port » dans ce RFC est une interface physique du routeur.
La *bibliothèque* composée des *classes* définies dans ce RFC 6956
permet de réaliser un routeur complet, mettant en œuvre toutes les
fonctions obligatoires du RFC 1812, notamment :
* Encapsuler et décapsuler les paquets pour la couche 2 (Ethernet, par
exemple),
* Envoyer et recevoir des paquets de taille allant jusqu'à la MTU du
lien, fragmenter les autres (pour IPv4),
* Traduire les adresses IP en adresses de la couche 2 (par exemple avec
ARP),
* Gérer ICMP, et notamment créer et envoyer les messages d'erreur ICMP
en réponse à des problèmes, ou bien lorsque le TTL tombe à zéro,
* Gérer les tampons d'entrée/sortie, la congestion, un juste traitement
des différents paquets,
* Trouver le routeur suivant ("next hop") lorsqu'il faut transmettre un
paquet,
* Être capable de faire tourner un IGP comme OSPF, dans certains cas un
EGP comme BGP, et accepter évidemment de simples routes statiques,
* Avoir toutes les fonctions de gestion du réseau qu'on attend :
statistiques, déboguage, journalisation...
Place maintenant au cœur de ce RFC, les classes qui y sont définies. Le
choix du groupe de travail forces <http://tools.ietf.org/wg/forces>
(section 3.2) a été de privilégier la souplesse en définissant plutôt
trop de classes que pas assez. Chaque classe ne va donc effectuer qu'un
minimum de fonctions, être logiquement séparée des autres classes et
notre routeur devra donc mettre en œuvre beaucoup de classes. Cela rend
donc le RFC très long et je ne vais donc pas parler de toutes les
classes, seulement de quelques unes choisies comme exemples. Pour la
totalité des classes, vous devez lire le RFC.
Les définitions des classes s'appuient sur un certain nombre de types
définis en section 4. Le RFC 5812 avait normalisé les types de base
comme uint32, char ou boolean. Notre RFC y ajoute quelques types
atomiques comme IPv4Addr, IPv6Addr, IEEEMAC (une adresse MAC),
PortStatusType (permettant d'indiquer si le port est activé ou non et
s'il fonctionne), VlanIDType pour le numéro de VLAN, etc. Il définit
également des types composés comme MACInStatsType (une entrée dans le
tableau de statistiques pour les paquets entrants, analysés à la couche
2), IPv6PrefixInfoType (un préfixe IPv6), IPv4UcastLPMStatsType (une
entrée dans le tableau de statistiques pour les paquets IPv4), etc.
Logiquement, les tableaux qui utilisent ces types sont également
définis comme IPv6PrefixTableType (un tableau de préfixes IPv6) ou
VlanInputTableType (un tableau de VLAN).
Un NE manipule des paquets donc il y a évidemment des types de paquets
parmi lesquels EthernetII, IPv4, IPv6, et même Arbitrary pour des
paquets quelconques.
Le tout est formellement décrit en XML dans la section 4.4. Ainsi, une
adresse IPv4 est :
<dataTypeDef>
<name>IPv4Addr</name>
<synopsis>IPv4 address</synopsis>
<typeRef>byte[4]</typeRef>
</dataTypeDef>
et une IPv6 est :
<dataTypeDef>
<name>IPv6Addr</name>
<synopsis>IPv6 address</synopsis>
<typeRef>byte[16]</typeRef>
</dataTypeDef>
Un type atomique comme la capacité du lien est définie par :
<dataTypeDef>
<name>LANSpeedType</name>
<synopsis>LAN speed type</synopsis>
<atomic>
<baseType>uint32</baseType>
<specialValues>
<specialValue value="0x00000001">
<name>LAN_SPEED_10M</name>
<synopsis>10M Ethernet</synopsis>
</specialValue>
<specialValue value="0x00000002">
<name>LAN_SPEED_100M</name>
<synopsis>100M Ethernet</synopsis>
</specialValue>
...
Même chose pour le PortStatusType mentionné plus haut :
<dataTypeDef>
<name>PortStatusType</name>
<synopsis>
Type for port status, used for both administrative and
operative status.
</synopsis>
<atomic>
<baseType>uchar</baseType>
<specialValues>
<specialValue value="0">
<name>Disabled</name>
<synopsis>Port disabled</synopsis>
</specialValue>
<specialValue value="1">
<name>Up</name>
<synopsis>Port up</synopsis>
</specialValue>
<specialValue value="2">
<name>Down</name>
<synopsis>Port down</synopsis>
</specialValue>
</specialValues>
</atomic>
</dataTypeDef>
<dataTypeDef>
Et les types structurés ? Un exemple est celui des statistiques sur les
paquets sortants, qui a deux composants (les champs des objets), un
pour les paquets transmis et un pour les paquets jetés :
<dataTypeDef>
<name>MACOutStatsType</name>
<synopsis>
Data type defined for statistics in EtherMACOut LFB.
</synopsis>
<struct>
<component componentID="1">
<name>NumPacketsTransmitted</name>
<synopsis>Number of packets transmitted</synopsis>
<typeRef>uint64</typeRef>
</component>
<component componentID="2">
<name>NumPacketsDropped</name>
<synopsis>Number of packets dropped</synopsis>
<typeRef>uint64</typeRef>
</component>
</struct>
</dataTypeDef>
Un autre exemple est le préfixe IPv6, qui réutilise le type atomique IPv6Addr :
<dataTypeDef>
<name>IPv6PrefixInfoType</name>
<synopsis>Data type for entry of IPv6 longest prefix match
table in IPv6UcastLPM LFB. The destination IPv6 address
of every input packet is used as a search key to look up
the table to find out a next hop selector.</synopsis>
<struct>
<component componentID="1">
<name>IPv6Address</name>
<synopsis>The destination IPv6 address</synopsis>
<typeRef>IPv6Addr</typeRef>
</component>
<component componentID="2">
<name>Prefixlen</name>
<synopsis>The prefix length</synopsis>
<atomic>
<baseType>uchar</baseType>
<rangeRestriction>
<allowedRange min="0" max="32"/>
</rangeRestriction>
</atomic>
</component>
...
Une fois tous ces types définis (et cela prend un bon bout du RFC), on
peut les utiliser pour bâtir les classes (section 5). Chaque classe va
être un gabarit dont on tirera les instances. Premier exemple : notre
routeur ForCES va évidemment avoir besoin de connaître Ethernet et de
traiter des paquets Ethernet, en envoi et en réception. Ethernet étant
très varié, commençons par un LFB ("Logical Function Block") qui
représente le niveau physique, EtherPHYCop. Ce LFB (cette partie
logique d'un routeur) a des composants pour indiquer l'état du port
(AdminStatus et OperStatus), composants qui peuvent être lus et
modifiés via le protocole ForCES. Ce LFB peut aussi générer des
événements comme par exemple le changement d'état d'un port
(PHYPortStatusChanged).
Au niveau au dessus (couche 2), il y a le LFB EtherMACIn. C'est par
exemple là que se trouve le composant LocalMACAddresses qui indique
l'adresse MAC. ou bien le composant PromiscuousMode qui dit si on veut
recevoir (ou pas) tous les paquets, même adressés à une autre machine.
Rappelez-vous : cette bibliothèque standard de ForCES privilégie la
souplesse, et crée donc *beaucoup* de LFB, pour pouvoir les arranger
comme souhaité. Rien que pour Ethernet, il y en a encore plusieurs
comme EtherEncap qui modélise les fonctions d'encapsulation et de
décapsulation des trames (ajout ou retrait des en-têtes Ethernet).
Mais on ne peut pas passer toute la journée sur les couches basses.
Pour « construire » un routeur par assemblage de LFB, il nous faut
maintenant des fonctions de manipulation d'IP. C'est le cas du LFB
IPv6Validator qui représente les fonctions de validation d'un paquet
(avant qu'on décide de le traiter, ou de le jeter s'il est invalide).
On suit le RFC 2460 et on considère comme invalide (ne devant pas être
transmis) les paquets ayant une taile inférieure à la taille minimale,
les paquets ayant une adresse source ou destination inacceptable, etc.
Il y a aussi des paquets nommés « exceptionnels » qui, sans être à
proprement parler invalides, ne pourront pas être transmis normalement
(par exemple ceux avec un "hop limit" descendu à zéro).
Et, ensuite, le travail sera fait par les LFB de transmission. Oui, ils
sont plusieurs. Pour IPv6, au moins IPv6UcastLPM (trouver le LPM,
"Longest Prefix Match", dans la table) et IPv6NextHop (sélection du
routeur suivant), sans compter des futurs LFB optionnels, par exemple
pour mettre en œuvre RPF.
Les LFB sont eux aussi formalisés en XML (section 6). Par exemple, le
dernier que nous avons vu, IPv6NextHop, sera :
<LFBClassDef LFBClassID="13">
<name>IPv6NextHop</name>
<synopsis>
The LFB abstracts the process of next hop information
application to IPv6 packets. It receives an IPv6 packet
with an associated next hop identifier (HopSelector),
uses the identifier as a table index to look up a next hop
table to find an appropriate output port.
</synopsis>
<inputPorts>
<inputPort group="false">
<name>PktsIn</name>
<synopsis>
A port for input of unicast IPv6 packets, along with
a HopSelector metadata.
</synopsis>
...
</inputPort>
</inputPorts>
<outputPorts>
...
</outputPorts>
<components>
<component componentID="1">
<name>IPv6NextHopTable</name>
<synopsis>
The IPv6NextHopTable component. A HopSelector is used
to match the table index to find out a row which
contains the next hop information result.
</synopsis>
<typeRef>IPv6NextHopTableType</typeRef>
</component>
</components>
</LFBClassDef>
Si la tête commence à vous tourner sérieusement, c'est sans doute
normal et prévu. Les auteurs du RFC ont pensé à vous et inclus une
section 7 qui décrit comment on crée une fonction de haut niveau à
partir des LFB de cette bibiothèque standard. Leur premier exemple est
la transmission de paquets IPv4 et le dessin ne compte pas moins de
treize LFB... (Dont, il est vrai, neuf juste pour Ethernet.) Pour
ajouter ARP, cela prend sept LFB (certains sont communs par exemple
EtherEncap est utilisé à la fois par la transmission de paquets IPv4 et
par ARP).
Les classes des LFB sont désormais dans un registre IANA
<http://www.iana.org/assignments/forces/forces.xml#logical-types>, ce
qui permettra d'en ajouter plus facilement d'autres.
Voilà, arrivé à ce stade, on a de quoi « fabriquer » un routeur ou plus
exactement de quoi le modéliser. En pratique, les vrais routeurs seront
seront bien différents mais ils exporteront aux clients ForCES des
fonctions représentées par ces LFB standards, fonctions qu'on pourra
configurer avec Forces.
---------------------------
Liste de diffusion du FRnOG
http://www.frnog.org/