Que fait un contrôleur OpenFlow ?
Un contrôleur OpenFlow est un programme qui reçoit des messages d’un commutateur et lui répond par des règles. Savoir le lire permet de dire ce que fera un réseau avant de le lancer.
Une équipe réseau d’université veut changer la politique de 40 commutateurs sans se connecter à chacun. Elle modifie quelques dizaines de lignes de Python, et tous les commutateurs suivent.
À la fin de cette leçon
Remarque
Je peux lire un petit contrôleur os-ken et dire ce que fait chacune de ses fonctions.
Mots-clés
| Mot | Ce que ça veut dire |
|---|---|
| os-ken | une bibliothèque Python pour écrire des contrôleurs OpenFlow |
| Gestionnaire | une fonction que le contrôleur appelle quand un événement arrive |
| Packet-in | le message par lequel le commutateur envoie un paquet au contrôleur |
| Flow-mod | le message par lequel le contrôleur pose une règle dans le commutateur |
| Packet-out | le message par lequel le contrôleur renvoie un paquet à émettre |
| Connexion | le lien entre un commutateur et son contrôleur |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Un contrôleur réagit à des événements
Un contrôleur os-ken ne tourne pas en boucle : il attend. Quand un message du commutateur arrive, il appelle la fonction prévue pour ce message.
On appelle cette fonction un gestionnaire. Une ligne qui commence par @set_ev_cls dit à quel événement il répond.
Trois messages font tout le travail
Le commutateur envoie un packet-in pour un paquet sans règle. Le contrôleur répond par un flow-mod pour poser une règle, et par un packet-out pour émettre ce premier paquet.
Après le flow-mod, les paquets suivants de la même conversation passent dans le commutateur, sans revenir au contrôleur.
Premier gestionnaire : la connexion
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
def switch_connecte(self, ev):
# Un commutateur vient de se connecter au contrôleur.
dp = ev.msg.datapath
parser = dp.ofproto_parser
ofp = dp.ofproto
vers_moi = [parser.OFPActionOutput(ofp.OFPP_CONTROLLER, ofp.OFPCML_NO_BUFFER)]
# Règle de priorité 0 : tout paquet sans règle vient au contrôleur.
self.ajouter_flux(dp, 0, parser.OFPMatch(), vers_moi)
Second gestionnaire : un packet-in
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def paquet_recu(self, ev):
# Le commutateur n'avait pas de règle et nous envoie le paquet.
msg = ev.msg
dp = msg.datapath
port_entree = msg.match['in_port']
trame = packet.Packet(msg.data).get_protocols(ethernet.ethernet)[0]
# trame.src et trame.dst sont les adresses MAC source et destination.
# ... ici le contrôleur décide : quel port, et faut-il poser une règle ?
# Puis il renvoie ce premier paquet avec un packet-out.
Exemple travaillé : ce que fait chaque gestionnaire
| Gestionnaire | Il répond à | Ce qu’il fait |
|---|---|---|
| switch_connecte | La connexion d’un commutateur | Pose la règle de priorité 0 qui envoie tout au contrôleur |
| paquet_recu | Un packet-in | Lit le port et les adresses, décide, renvoie le paquet |
| ajouter_flux | Aucun événement | Fonction d’aide qui envoie un flow-mod |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Regarder un contrôleur sans le terminer
Les premières commandes regardent le contrôleur donné par votre labo, sans le changer. Elles listent ses gestionnaires et relisent un en-tête Ethernet avec la même bibliothèque.
Ensuite on branche le commutateur d’essai demo sur un contrôleur absent, pour voir ce que veut dire « connecté ». Enfin on pose à la main une règle par défaut, puis une règle apprise.
Lister les gestionnaires du contrôleur donné
grep -n "@set_ev_cls" /etc/sdnlab/switch.pyAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Les numéros réservés d’OpenFlow
python3 -W ignore -c "from os_ken.ofproto import ofproto_v1_3 as o; print(o.OFPP_FLOOD, o.OFPP_CONTROLLER, o.OFP_VERSION)"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Relire une trame comme le fait os-ken
python3 -W ignore -c "from os_ken.lib.packet import ethernet; print(ethernet.ethernet.parser(ethernet.ethernet('aa:00:00:00:00:02', 'aa:00:00:00:00:01', 2048).serialize(bytearray(), None))[0])"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Créer le commutateur demo
sudo ovs-vsctl --may-exist add-br demo -- set bridge demo datapath_type=system protocols=OpenFlow13 fail-mode=secure -- --may-exist add-port demo p1 -- set interface p1 type=internal ofport_request=1 -- --may-exist add-port demo p2 -- set interface p2 type=internal ofport_request=2 -- --may-exist add-port demo p3 -- set interface p3 type=internal ofport_request=3Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le brancher sur un contrôleur absent
sudo ovs-vsctl set-controller demo tcp:127.0.0.1:6633Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Est-il connecté ?
sudo ovs-vsctl get controller demo is_connectedAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le débrancher
sudo ovs-vsctl del-controller demoAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Poser la règle par défaut vers le contrôleur
printf 'priority=0,actions=CONTROLLER:65535\n' | sudo ovs-ofctl -O OpenFlow13 replace-flows demo -Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Où va un premier paquet ?
sudo ovs-appctl ofproto/trace demo in_port=1,dl_src=aa:00:00:00:00:01,dl_dst=aa:00:00:00:00:02 | grep -A 2 "^ 0\."Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Poser la règle que le contrôleur aurait écrite
sudo ovs-ofctl -O OpenFlow13 add-flow demo "priority=1,in_port=1,dl_src=aa:00:00:00:00:01,dl_dst=aa:00:00:00:00:02,actions=output:2"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Où va le paquet suivant ?
sudo ovs-appctl ofproto/trace demo in_port=1,dl_src=aa:00:00:00:00:01,dl_dst=aa:00:00:00:00:02 | grep -A 2 "^ 0\."Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Erreur fréquente
Attention
Beaucoup de gens pensent que le contrôleur décide à nouveau pour chaque paquet. Il ne décide que pour le premier. Une fois la règle posée, le commutateur la suit seul, ce qui garde le réseau rapide. Attention : une règle posée continue de servir même si une machine change de port.