User Tools

Site Tools


reseau:ryu-overview

RYU SDN overview

inlinetoc

Ryu est une infrastructure réseau définie par logiciel et basée sur les composants. Ryu fournit des composants logiciels avec des API bien définies qui permettent aux développeurs de créer facilement de nouvelles applications de gestion et de contrôle de réseau.

Ryu prend en charge divers protocoles pour la gestion des périphériques réseau, tels que OpenFlow (versions 1.0, 1.2, 1.3, 1.4, 1.5) , Netconf, OF-config, etc.

Mise en oeuvre

Installation

Utiliser la commande pip est l’option la plus simple:

$ pip install ryu

On peut également l'installer à partir du code source:

$ git clone git://github.com/osrg/ryu.git
$ cd ryu
$ python ./setup.py install

Applications

Ryu est déjà livré avec de nombreuses applications de référence avec l'API REST dans le répertoire /usr/local/lib/python3.6/site-packages/ryu/app, tel que rest_router.py. Ryu est livré avec de nombreuses applications de référence avec l'API REST dans le répertoire ryu/app, tel que :

  • example_switch_13
  • simple_monitor_13
  • simple_switch_rest_13

example_switch_13

Les concentrateurs de commutation remplissent diverses fonctions. example_switch_13 est un hub de commutation ayant les fonctions simples suivantes.

  • Apprend l'adresse MAC de l'hôte connecté à un port et la conserve dans la table des adresses MAC.
  • Lors de la réception de paquets adressés à un hôte déjà appris, les transfère sur le port connecté à l'hôte.
  • Lors de la réception de paquets adressés à un hôte inconnu, effectue une inondation. Pour démarrer l'application il faut définir OpenFlow13 pour la version OpenFlow, puis démarrer le hub de commutation avec la commande suivante :
$ ryu-manager --verbose ryu.app.example_switch_13
loading app ryu.app.example_switch_13
loading app ryu.controller.ofp_handler
instantiating app ryu.app.example_switch_13 of ExampleSwitch13
instantiating app ryu.controller.ofp_handler of OFPHandler
BRICK ExampleSwitch13
  CONSUMES EventOFPPacketIn
  CONSUMES EventOFPSwitchFeatures
BRICK ofp_event
  PROVIDES EventOFPPacketIn TO {'ExampleSwitch13': set(['main'])}
  PROVIDES EventOFPSwitchFeatures TO {'ExampleSwitch13': set(['config'])}
  CONSUMES EventOFPErrorMsg
  CONSUMES EventOFPHello
  CONSUMES EventOFPEchoRequest
  CONSUMES EventOFPEchoReply
  CONSUMES EventOFPPortStatus
  CONSUMES EventOFPSwitchFeatures
  CONSUMES EventOFPPortDescStatsReply
connected socket:<eventlet.greenio.base.GreenSocket object at 0x7f1239937a90> address:('127.0.0.1', 37898)
hello ev <ryu.controller.ofp_event.EventOFPHello object at 0x7f1239927d50>
move onto config mode
EVENT ofp_event->ExampleSwitch13 EventOFPSwitchFeatures
switch features ev version=0x4,msg_type=0x6,msg_len=0x20,xid=0xea43ed30,OFPSwitchFeatures(auxiliary_id=0,capabilities=79,datapath_id=1,n_buffers=256,n_tables=254)
move onto main mode

La connexion à OVS peut prendre un certain temps.

Maintenant, OVS a été connecté, la négociation a été effectuée, l'entrée de flux Table-miss a été ajoutée et le concentrateur de commutation est dans l'état en attente de Packet-In.

Confirmer que l'entrée de flux Table-miss a été ajoutée.

commutateur: s1:

$ ovs-ofctl -O openflow13 dump-flows s1
OFPST_FLOW reply (OF1.3) (xid=0x2):
 cookie=0x0, duration=105.975s, table=0, n_packets=0, n_bytes=0, priority=0 actions=CONTROLLER:65535

Le niveau de priorité est 0, pas de correspondance. CONTROLLER est spécifié pour l'action. La taille des données de transfert est 65535 (0xffff = OFPCMLNOBUFFER) est spécifié.

Confirmation de l'opération

Exécuter la commande ping de l’hôte 1 à l’hôte 2.

  • Demande ARP: À ce stade, l'hôte 1 ne connaît pas l'adresse MAC de l'hôte 2; par conséquent, avant la demande d'écho ICMP, une demande ARP doit être diffusée. Le paquet de diffusion est reçu par l’hôte 2 et l’hôte
  • Réponse ARP: En réponse à l'ARP, l'hôte 2 renvoie une réponse ARP à l'hôte 1.
  • Demande d'écho ICMP: Maintenant, l'hôte 1 connaît l'adresse MAC de l'hôte 2, l'hôte 1 envoie une demande d'écho à l'hôte 2.
  • ICMP echo réponse: Comme l'hôte 2 connaît déjà l'adresse MAC de l'hôte 1, celui-ci renvoie une réponse d'écho à l'hôte 1.

Des communications comme celles décrites ci-dessus sont supposées avoir lieu.

Tout d'abord, vérifier le tableau de flux.

commutateur: s1:

$ ovs-ofctl -O openflow13 dump-flows s1
OFPST_FLOW reply (OF1.3) (xid=0x2):
 cookie=0x0, duration=417.838s, table=0, n_packets=3, n_bytes=182, priority=0 actions=CONTROLLER:65535
 cookie=0x0, duration=48.444s, table=0, n_packets=2, n_bytes=140, priority=1,in_port=2,dl_dst=00:00:00:00:00:01 actions=output:1
 cookie=0x0, duration=48.402s, table=0, n_packets=1, n_bytes=42, priority=1,in_port=1,dl_dst=00:00:00:00:00:02 actions=output:2

En plus de l'entrée de flux Table-Miss, des entrées de flux de niveau de priorité 1 ont été enregistrées.

  • Port de réception (in_port): 2, Adresse MAC de destination (dl_dst): hôte 1 → Action (actions): Transfert sur le port 1
  • Port de réception (in_port): 1, Adresse MAC de destination (dl_dst): hôte 2 → Action (actions): Transfert sur le port 2

L'entrée (1) a été référencée deux fois (n_packets) et l'entrée (2) a été référencée une fois. Etant donné que (1) est une communication entre l'hôte 2 et l'hôte 1, la réponse ARP et la réponse ICMP echo doivent correspondre. (2) est une communication de l'hôte 1 à l'hôte 2 et, étant donné que la demande ARP est diffusée, ceci est supposé être une demande d'écho ICMP.

Dans la sortie du journal de example_switch_13 on peut voir :

contrôleur: c0:

EVENT ofp_event->ExampleSwitch13 EventOFPPacketIn
packet in 1 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff 1
EVENT ofp_event->ExampleSwitch13 EventOFPPacketIn
packet in 1 00:00:00:00:00:02 00:00:00:00:00:01 2
EVENT ofp_event->ExampleSwitch13 EventOFPPacketIn
packet in 1 00:00:00:00:00:01 00:00:00:00:00:02 1
  • Le premier paquet entrant est la demande ARP émise par l'hôte 1; il s'agit d'une diffusion; l'entrée du flux n'est pas enregistrée et seul le paquet sortant est émis.
  • Le second est la réponse ARP renvoyée par l'hôte 2 et, l'adresse MAC de destination étant l'hôte 1, l'entrée de flux susmentionnée (1) est enregistrée.
  • Le troisième est la demande d'écho ICMP envoyée de l'hôte 1 à l'hôte 2 et l'entrée de flux (2) est enregistrée.

La réponse d'écho ICMP renvoyée de l'hôte 2 à l'hôte 1 correspond à l'entrée de flux déjà enregistrée (1) et est donc transférée à l'hôte 1 sans émettre de packet-in.

simple_monitor_13

Les réseaux sont déjà devenus l’infrastructure de nombreux services et entreprises; on s’attend donc à maintenir un fonctionnement normal et stable. Cela dit, il y a toujours des problèmes.

Lorsqu'une erreur survient sur le réseau, la cause doit être identifiée et l'opération restaurée rapidement. Il va sans dire que pour détecter les erreurs et identifier les causes, il est nécessaire de connaître régulièrement l’état du réseau. Par exemple, en supposant que le volume de trafic d'un port d'un périphérique réseau indique une valeur très élevée, qu'il s'agisse d'un état anormal ou généralement ainsi et quand il est devenu ainsi, il est impossible de déterminer si le volume de trafic du port n'a pas été mesuré en continu .

Pour cette raison, une surveillance constante de la santé d'un réseau est essentielle pour un fonctionnement continu et sécurisé des services ou des entreprises utilisant ce réseau. Bien entendu, la simple surveillance des informations sur le trafic ne constitue pas une garantie parfaite, mais cette section explique comment utiliser OpenFlow pour acquérir des informations statistiques relatives à un commutateur.

Pour démarrer l'application il faut définir OpenFlow13 pour la version OpenFlow, puis démarrer le hub de commutation avec la commande suivante :

$ ryu-manager --verbose ryu.app.simple_monitor_13
loading app ryu.app.simple_monitor_13
loading app ryu.controller.ofp_handler
instantiating app ryu.app.simple_monitor_13 of SimpleMonitor13
instantiating app ryu.controller.ofp_handler of OFPHandler
BRICK SimpleMonitor13
  CONSUMES EventOFPPacketIn
  CONSUMES EventOFPPortStatsReply
  CONSUMES EventOFPStateChange
  CONSUMES EventOFPFlowStatsReply
  CONSUMES EventOFPSwitchFeatures
BRICK ofp_event
  PROVIDES EventOFPPacketIn TO {'SimpleMonitor13': set(['main'])}
  PROVIDES EventOFPPortStatsReply TO {'SimpleMonitor13': set(['main'])}
  PROVIDES EventOFPStateChange TO {'SimpleMonitor13': set(['main', 'dead'])}
  PROVIDES EventOFPFlowStatsReply TO {'SimpleMonitor13': set(['main'])}
  PROVIDES EventOFPSwitchFeatures TO {'SimpleMonitor13': set(['config'])}
  CONSUMES EventOFPPortStatus
  CONSUMES EventOFPSwitchFeatures
  CONSUMES EventOFPEchoReply
  CONSUMES EventOFPPortDescStatsReply
  CONSUMES EventOFPErrorMsg
  CONSUMES EventOFPEchoRequest
  CONSUMES EventOFPHello
connected socket:<eventlet.greenio.base.GreenSocket object at 0x7fbab7189750> address:('127.0.0.1', 37934)
hello ev <ryu.controller.ofp_event.EventOFPHello object at 0x7fbab7179a90>
move onto config mode
EVENT ofp_event->SimpleMonitor13 EventOFPSwitchFeatures
switch features ev version=0x4,msg_type=0x6,msg_len=0x20,xid=0x21014c5c,OFPSwitchFeatures(auxiliary_id=0,capabilities=79,datapath_id=1,n_buffers=256,n_tables=254)
move onto main mode
EVENT ofp_event->SimpleMonitor13 EventOFPStateChange
register datapath: 0000000000000001
send stats request: 0000000000000001
EVENT ofp_event->SimpleMonitor13 EventOFPFlowStatsReply
EVENT ofp_event->SimpleMonitor13 EventOFPPortStatsReply
datapath         in-port  eth-dst           out-port packets  bytes
---------------- -------- ----------------- -------- -------- --------
datapath         port     rx-pkts  rx-bytes rx-error tx-pkts  tx-bytes tx-error
---------------- -------- -------- -------- -------- -------- -------- --------
0000000000000001        1        0        0        0        0        0        0
0000000000000001        2        0        0        0        0        0        0
0000000000000001        3        0        0        0        0        0        0
0000000000000001 fffffffe        0        0        0        0        0        0

À ce stade, il n'y a pas d'entrée de flux (l'entrée de flux table-miss n'est pas affichée) et le nombre de chaque port est égal à 0.

Exécutons la commande ping de l’hôte 1 à l’hôte 2.

hôte: h1:

PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_req=1 ttl=64 time=94.4 ms

--- 10.0.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 94.489/94.489/94.489/0.000 ms

Le transfert de paquets et l'entrée de flux sont enregistrés et les informations statistiques sont modifiées.

contrôleur: c0:

datapath         in-port  eth-dst           out-port packets  bytes
---------------- -------- ----------------- -------- -------- --------
0000000000000001        1 00:00:00:00:00:02        2        1       42
0000000000000001        2 00:00:00:00:00:01        1        2      140
datapath         port     rx-pkts  rx-bytes rx-error tx-pkts  tx-bytes tx-error
---------------- -------- -------- -------- -------- -------- -------- --------
0000000000000001        1        3      182        0        3      182        0
0000000000000001        2        3      182        0        3      182        0
0000000000000001        3        0        0        0        1       42        0
0000000000000001 fffffffe        0        0        0        1       42        0

Selon les informations statistiques d’entrée de flux, le trafic mis en correspondance avec le flux du port de réception 1 est enregistré sous la forme d’un paquet de 42 octets. Avec le port de réception 2, il s'agit de 2 paquets, 140 octets.

Selon les informations statistiques du port, le nombre de paquets reçus (rx-pkts) du port 1 est égal à 3, le nombre d'octets reçus (rx-octets) est de 182 octets. Avec le port 2, il s'agit de 3 paquets et de 182 octets, respectivement.

Les chiffres ne concordent pas entre les informations statistiques d'entrée de flux et celles de port. La raison en est que les informations statistiques d'entrée de flux sont les informations des paquets qui correspondent à l'entrée et ont été transférés. Cela signifie que les paquets pour lesquels Packet-In est émis par Table-miss et sont transférés par Packet-Out ne sont pas inclus dans ces statistiques.

Dans ce cas, trois paquets correspondant à la première requête ARP diffusée par l'hôte 1, la réponse ARP renvoyée par l'hôte 2 à l'hôte 1 et la demande d'écho émise par l'hôte 1 à l'hôte 2, sont transférés par Packet-Out. Pour la raison ci-dessus, le nombre de statistiques portuaires est supérieur à celui de la saisie de flux.

simple_switch_rest_13

Ryu a une fonction de serveur Web correspondant à WSGI. En utilisant cette fonction, il est possible de créer une API REST, utile pour établir des liens avec d'autres systèmes ou navigateurs.

WSGI désigne un cadre unifié permettant de connecter des applications Web et des serveurs Web en Python.

Avec simple_switch_rest_13.py, deux classes sont définies :

  • La première classe est la classe de contrôleur SimpleSwitchController, qui définit l'URL destinée à recevoir la demande HTTP et la méthode correspondante.
  • La deuxième classe est SimpleSwitchRest13, qui est une extension de ”Switching Hub”, pour pouvoir mettre à jour la table des adresses MAC.

Pour démarrer l'application il faut définir OpenFlow13 pour la version OpenFlow, puis démarrer le hub de commutation avec la commande suivante :

$ sudo ovs-vsctl set Bridge s1 protocols=OpenFlow13
$ ryu-manager --verbose ryu.app.simple_switch_rest_13
loading app ryu.app.simple_switch_rest_13
loading app ryu.controller.ofp_handler
creating context wsgi
instantiating app ryu.app.simple_switch_rest_13 of SimpleSwitchRest13
instantiating app ryu.controller.ofp_handler of OFPHandler
BRICK SimpleSwitchRest13
  CONSUMES EventOFPPacketIn
  CONSUMES EventOFPSwitchFeatures
BRICK ofp_event
  PROVIDES EventOFPPacketIn TO {'SimpleSwitchRest13': set(['main'])}
  PROVIDES EventOFPSwitchFeatures TO {'SimpleSwitchRest13': set(['config'])}
  CONSUMES EventOFPSwitchFeatures
  CONSUMES EventOFPPortDescStatsReply
  CONSUMES EventOFPErrorMsg
  CONSUMES EventOFPEchoRequest
  CONSUMES EventOFPEchoReply
  CONSUMES EventOFPHello
  CONSUMES EventOFPPortStatus
(24728) wsgi starting up on http://0.0.0.0:8080
connected socket:<eventlet.greenio.base.GreenSocket object at 0x7f2daf3d7850> address:('127.0.0.1', 37968)
hello ev <ryu.controller.ofp_event.EventOFPHello object at 0x7f2daf38c890>
move onto config mode
EVENT ofp_event->SimpleSwitchRest13 EventOFPSwitchFeatures
switch features ev version=0x4,msg_type=0x6,msg_len=0x20,xid=0x86fc9d2f,OFPSwitchFeatures(auxiliary_id=0,capabilities=79,datapath_id=1,n_buffers=256,n_tables=254)
move onto main mode

Dans le message au moment du démarrage, il y a une ligne indiquant «(31135) wsgi démarrant à http://0.0.0.0:8080/» et indiquant que le serveur Web a démarré au numéro de port 8080.

Ensuite, faire un ping de l’hôte 1 à l’hôte 2.

$ ping -c 1 h2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_req=1 ttl=64 time=84.1 ms

--- 10.0.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 84.171/84.171/84.171/0.000 ms

Sur Ryu on peut voir Packet-In c'est produit trois fois.

EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketIn
packet in 1 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff 1
EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketIn
packet in 1 00:00:00:00:00:02 00:00:00:00:00:01 2
EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketIn
packet in 1 00:00:00:00:00:01 00:00:00:00:00:02 1

Exécuter l’API REST qui acquiert la table MAC du concentrateur de commutation. Cette fois, utiliser la commande curl pour appeler l'API REST.

$ curl -X GET http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
{"00:00:00:00:00:02": 2, "00:00:00:00:00:01": 1}

On peut constater que deux hôtes, l'hôte 1 et l'hôte 2, ont été appris dans la table des adresses MAC.

Cette fois, stocker au préalable les deux hôtes, l'hôte 1 et l'hôte 2, dans la table des adresses MAC et exécuter la commande ping. Arrêter temporairement le concentrateur de commutation et Mininet une fois. Ensuite, relancer Mininet, définir la version OpenFlow sur OpenFlow13, puis démarrer le hub de commutation.

...
(26759) wsgi starting up on http://0.0.0.0:8080/
connected socket:<eventlet.greenio.GreenSocket object at 0x2afe6d0> address:('127.0.0.1', 48818)
hello ev <ryu.controller.ofp_event.EventOFPHello object at 0x2afec10>
move onto config mode
EVENT ofp_event->SimpleSwitchRest13 EventOFPSwitchFeatures
switch features ev version: 0x4 msg_type 0x6 xid 0x96681337 OFPSwitchFeatures(auxiliary_id=0,capabilities=71,datapath_id=1,n_buffers=256,n_tables=254)
switch_features_handler inside sub class
move onto main mode

Ensuite, appeler l'API REST pour mettre à jour la table d'adresses MAC pour chaque hôte. Le format de données lors de l'appel de l'API REST doit être {«mac»: «adresse MAC», «port»: numéro de port de connexion}.

$ curl -X PUT -d '{"mac" : "00:00:00:00:00:01", "port" : 1}' http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
{"00:00:00:00:00:01": 1}
$ curl -X PUT -d '{"mac" : "00:00:00:00:00:02", "port" : 2}' http://127.0.0.1:8080/simpleswitch/mactable/0000000000000001
{"00:00:00:00:00:02": 2, "00:00:00:00:00:01": 1}

Lorsque ces commandes sont exécutées, l'entrée de flux correspondant aux hôtes 1 et 2 est enregistrée.

Maintenant, exécuter un ping de l’hôte 1 à l’hôte 2.

PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_req=1 ttl=64 time=4.62 ms

--- 10.0.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 4.623/4.623/4.623/0.000 ms
...
move onto main mode
(28293) accepted ('127.0.0.1', 44453)
127.0.0.1 - - [19/Nov/2013 19:59:45] "PUT /simpleswitch/mactable/0000000000000001 HTTP/1.1" 200 124 0.002734
EVENT ofp_event->SimpleSwitchRest13 EventOFPPacketIn
packet in 1 00:00:00:00:00:01 ff:ff:ff:ff:ff:ff 

À ce stade, l'entrée de flux existe pour les commutateurs. L'entrée de paquet ne survient que lorsqu'une demande ARP est envoyée de l'hôte 1 à l'hôte 2 et n'est pas déclenchée pour un échange de paquets ultérieur.

reseau/ryu-overview.txt · Last modified: 2023/03/16 13:53 by 127.0.0.1