L'idée de base de cette implémentation est de modifier le moins possible la souche originelle. Nous nous sommes efforcés de repérer les points précis où nous avions besoin d'insérer du code, et nous avons fait appel à des fonctions, réalisées par nos soins, pour produire les effets escomptés. Ces fonctions sont écrites dans des fichiers .c figurant dans un reportoire ndpd-uhmma.
Ces fichiers sont préfixés par les initiales de la machine auquel ils sont relatifs : mh-xxx.c pour le Mobile Host, ma- pour le Mobility Agent et bs- pour la Base Station. Le xxx représente une fonctionnalité. Par exemple, ma-smooth.c va regrouper les fonctions du MA relatives au smooth handoff. A noter qu'il existe quelques fichiers mu-xxx.c qui contiennent des fonctions utilisées par plusieurs composants.
Le code ajouté à ndpd a été entouré de define. Nous avons trois define différents, un pour chaque entité. UHMMA pour le Mobile Host, uMIP pour le Mobility Agent et uMIPBS pour la Base Station.
Il est donc possible de compiler ndpd-host avec ou sans support pour HMIP, et ndpd-router pour être un MA ou une BS ou encore aucun des deux. Je rappelle ici qu'un MA ne peut pas être un Home Agent, alors qu'un BS si.
Rappels importants :
Un major move est un mouvement qui s'est effectué vers ou depuis le réseau mère. Il ne faut donc pas confondre major move avec macro move, qui est un mouvement entre deux domaines différents, par opposition à micro move qui est un mouvement à l'intérieur d'un domaine. Un major move peut donc être un micro move.
Un minor move est un mouvement dans lequel le réseau mère n'est ni le réseau d'origine ni le réseau d'arrivée. Un minor move peut être un macro move ou un micro move.
Major move et mino move sont des termes définis par l'implémentation de Mobile IPv6. Macro et micro move sont des termes définis par Hierarchical Mobile IPv6.
Nous avons besoin d'un certain nombre de variables pour mémoriser les informations relatives au mode de fonctionnement du mobile. Le mobile est capable de fonctionner selon trois modes distincts.
Nous avons décider d'utiliser une batterie de fonctions dissiminées dans plusieurs fichiers c. Nous avons besoin d'avoir des variables globales.
Plutôt que d'utiliser une multitude de variables globales, nous utilisons une structure qui contient toutes les variables dont on a besoin. L'avantage de cette méthode est une meilleure lisibilité du code. Notre structure s'appelle "global", il est donc facile lorsque l'on lit "global.nbBack" de savoir où et comment est définie/déclarée cette variable.
Voici la liste des variables utilisées avec leur fonction :
TAILQ_HEAD(, prefix) Vpref; /* list of voca prefix */ char MA_mode; /* MA mode 1|2 */ char mode du mobile; /* the current mobility mode */ char mode du mobile_init; /* the user mobility mode choice */ char need_to_swap; /* is set while swapping */ char swap_in_progress; /* */ char * reemit_reg_packet; /* registration packet */ int seq_num; /* sequence number */ short nbBack; /* number of waitin Back */ struct corr * HA; /* Home agent */ struct in6_addr MA_address;/* local MA */ struct in6_addr MA_old; /* previous MA */ struct in6_addr MA_readed; /* MA readed in the rt adv*/ struct in6_addr VCOA; /* the vcoa itself */ struct timeout * back_timer; /* */ struct timeout * reemis_timer; /* retransmit timer */ struct timeout * uMIP_timer; /* old position timer */ u_char MA_plen; /* prefix length of virtual network */ u_char site_len; /* site prefix length */ u_char reg_ret; /* number of retransmissions */ u_char reg_ret_max; /* max. number of retransmissions */ u_short pkt_size; /* size of the reemission packet */
Nous utilisons dans l'implémentation un certain nombre de timers. Les durée de ces timers sont initialisées avec des valeurs par défaut. Nous offrons aux utilisateurs la possibilité d'initialiser ces valeurs avec les temps qu'il désire (cf. ). Pour stocker ces temps nous utilisons une autre structure, struct temp. Elle contient les variables suivantes :
u_int forward; /* forwarding while moving between two domain */ u_int home; /* forwarding when returning to home */ u_int lifetime; /* default lifetime sent to a MA */ u_int position; /* interval for sending old position */ u_int refresh; /* default refresh */ u_int retransmission;/* interval between two registrations */ u_int smooth; /* interval between two smooth handoffs */
ndpd-host possède deux fonctions d'initialisation. La première est pour le protocole NDP et la seconde est pour la mobilité. C'est à l'intérieur de celle-ci que nous faisons appel à notre propre fonction d'initialisation, qui va positionner quelques variables ; on initialise les différentes adresses que nous utiliserons par la suite à l'adresse indéterminée et le compteur de séquence à zéro.
Les valeurs des temporisations sont entrées par l'utilisateur par l'intermédiaire du fichier /etc/mobile6. Nous utilisons également cette méthode pour
Pour affecter ces variables nous utilisons donc des fonctions que nous avons été obligé de laisser dans le fichier mc-file.c de MIP.
En effet, le déplacement de nos fonctions dans un fichier à part entraine beaucoup de complications (à cause notament, d'une multitude de variables statiques et globales au fichier). Nous avons donc ajouté nos fonctions directement dans mc-file.c, encadrées par un define.
Nous ne précisons pas ici les algorithmes utilisés, car il sagit d'une simple copie de ce de Mobile IPv6.
Ce qui change dans l'approche hiérarchique, c'est le comportement du mobile après un mouvement. Nous avons donc laisser les procédures de détection de mouvement faire leur travail et nous avons insérer quelques tests avant d'exécuter l'action de base consécutive à la détection de mouvement (ie. envoi de binding aux correspondants) pour prendre en compte la mobilité hiérarchique.
Les fonctions qui sont appelées après un mouvement sont major_move et minor_move. Un major move est un mouvement dans lequel intervient le réseau mère et un minor move est un mouvement entre deux réseaux visités.
Ces deux fonctions mettent à jour un certain nombre de variables (telle la care-of) pour prendre en compte la nouvelle position, puis font appel à mobile_move.
mobile_move va envoyer les binding updates, et ce selon le standard Mobile IPv6. C'est donc autour de cet appel que nous allons travailler.
Il faut ici tenir compte du mode de mobilité actuel.
Ceci est valable pour major_move et minor_move.
Les choses sont en fait plus complexe car il faut tenir compte des disponibilités des modes après un mouvement. Nous reviendrons sur cet aspect dans la section .
si mode du mobile == 2 alors envoyer enregistrement au MA terminer si mode du mobile == 1 alors envoyer enregistrement au MA gérer la mobilité selon MIP
Un point à aborder ici est l'utilisation des routers adv. pour la détection de mouvement. Le mobile reçoit un router adv. d'un routeur qu'il ne connait pas. Il en clonclut qu'il a peut être effectuer un mouvement. Il sollicite alors l'ancien routeur. Si celui-ci répond, pas de mouvement. Si l'ancien ne répond pas, alors mouvement. Les procédures de gestion de mouvement sont appelées.
Le protocole HMIP véhicule l'adresse du MA local à l'intérieur des routers adv. Dans la fonction qui traite le router adv.(recv_rtadv de icmp.c), nous regardons s'il apparait une option MA. Si oui nous stockons l'adresse du MA et le mode du MA dans des variables temporaires. Ces variables seront utilisées pour notre gestion de micro/macro mobilité.
Pour suivre la phylosophie du code MIP, nous avons créer deux fonctions : send_uhmma_major_reg et send_uhmma_minor_reg. Ces fonctions se trouvent dans mh-reg.c, elles seront appelée par major_move et minor_move.
Nous sommes ici en présence d'un mouvement vers ou depuis le réseau mère.
Si nous venons du réseau mère, il faut :
Note : pour la gestion des ack se référer à la section . nous ne parlons pas des ack dans le cas du mode 1. Nous utilisons pour cela les mécanismes de MIPv6 qui fonctionne très bien pour ce mode.
Si nous arrivons sur le réseau mère :
Nous utilisons cette fonction pour envoyer un paquet d'enregistrement au MA courant. C'est donc la variable globale MA courant qui est utilisée pour destination du paquet.
Cette fonction reçoit en paramètre un flag qui indique si oui ou non le processus de retransmission du paquet doit être engagé ou non.
Ce processus est réalisé en sauvegardant une copie du paquet d'enregistrement en mémoire (ainsi que sa taille) et en lançant un timer2 avec en traitant la fonction resend_reg.
Lorsque le timer expire, le traitant est appelé. Ce traitant augmente le compteur de séquence (dans la variable ET dans le paquet lui même), renvoie le paquet et relance le même timer avec lui même en traitant. On créait ainsi un processus de ré émission qu'il est possible de stopper par l'arrivée des ack escomptés (cf.
). Nous verrons en l'algorithme de cette fonction. parle des changements de mode, en effet il est possible qu'un mobile abandonne sa phase d'enregistrement qui semble infructueuse pour passer en mode MIP.
Lorsque le mobile retourne sur le réseau mère après x mouvements, il faut le replacer dans un état satisfaisant (comme s'il venait de booter sur le réseau mère) ; retirer les adresses virtuelles, initialiser quelques variables. Nous ne pouvons pas effacer les adresses de HMIP dès que l'on arrive sur le réseau mère, car nous les utilisons pour faire divers controles lors de la reception des ack. Nous replaçons à zéro (adresse indéterminée) les quelques variables : MA_address, MA_old et VCOA.
Note : les VCOA ne sont pas retirer ici car elles ont été dépréciées lors de la gestion du mouvement. Le temp de dépréciation et le temps donné à clear_back avant son exécution est le même, ainsi les deux actions se dérouleront simultanément.
Nous gérons ici les mouvements entre deux réseaux. Nous devons savoir si ces deux réseaux appartiennent au même domaine ou non, car le traitement diffère si l'on utilise la gestion hiérarchique.
Si les deux réseaux sont du même domaine :
Si les deux réseaux appartiennent à des domaines différents :
update_cn_list : la mise à jour des correspondants est faite pour détecter s'il faut envoyer une PCOA ou un VCOA dans les binding updates. Il est important de faire ceci ici, car en sortie de cette fonction nous allons enchainer sur l'envoi des binding updates (cf. 1.2). Cette fonction est une boucle qui passe en revue tous les correspondants. Pour chacun d'entre eux, on regarde si ce correspondant est dans le domaine actuel, si oui le champ VCOA de la structure doit être initialisé avec l'adresse indeterminée. Sinon, la nouvelle VCOA est copié dans ce champ. Si le mobile fonctionne en mode MIP, ce champ est obligatoirement initialisé à l'adresse indeterminée. Ce champ sera utilisé lors de l'envoi de binding updates (cf. ).
Nous parlons de cette fonction ici, bien qu'elle soit effectivement activée par le processus de réception des ack.
Cette fonction a pout but d'envoyer périodiquement un paquet binding update au MA pour lui confirmer que le mobile est toujours à sa place. Si cela n'est pas fait le mobile se vera retiré de la liste des mobiles et ne sera donc plus géré localement. Ce paquet est en fait identique à un binding update sauf qu'il contient le flag OLD_POSITION_FLAG. Nous copions donc le code d'envoi de binding dans MIP pour notre fonction. Nous y ajoutons simplement en fin, le lancement du timer uMIP_timer avec le traitant send_old_position. Ainsi cette fonction se relance indéfiniment. On peut évidement stopper ce processus en détruisant le timer. Cette fonction incrémente le compteur de séquence à chaque occurence, elle utilise la PCOA pour remplir le champ source du paquet et l'adresse du MA local pour le champ destination.
Ce paragraphe porte uniquement sur le mode 1 de fonctionnement, dans le cas 2, les binding updates sont envoyés par le MA. L'envoi est assuré par la fonction mobile_move. Cette fonction est divisée en trois partie :
Note importante : rappelons nous que nous ne pouvons arriver dans cette fonction que si nous fonctionnons en mode MODE1 ou MIP.
Eliminons le cas retour sur réseau mère, car le code pour MIP et HMIP est le même : se dé enregistrer de tous les correspondants - > pas de modification.
Par contre pour les deux autres cas, nous devons tester l'état du mobile et le type de mouvement avant de prendre une décision quant à l'envoi d'un binding update. Ces tests se placent devant le code d'envoi de binding updates de MIP.
si mobility mode == MODE1 alors si MA précédent != MA courant alors envoyer binding sinon envoyer binding (code normal de MIPv6)Les fonctions d'envoi de binding (il y en a deux, une étant spécifique au HA) sont send_bnd_upd et send_home_reg. Ces fonctions ont été entièrement réécrites dans le fichier mh-send.c. C'est pourquoi en début de mc-send.c nous avons ajouté un ifndef UHMMA pour exclure tout le fichier.
si cop.VCOA est l'adresse indéterminée alors envoyer binding classique sinon envoyer binding avec VCOA
Notre fonction send_home_reg fonctionne selon le même algorithme.
La première chose à aborder ici est le fait que les ack de MIP et du mode 1 sont entièrement gérés par le code de MIP que nous n'avons pas modifié. Nous ne nous en préoccupons pas. Nous verrons en détails la gestion des ack en provenance du MA pour le mode 1 et des ack. du HA et du MA pour le mode 2.
Selon le type de mouvement que l'on vient d'effectuer, nous devons nous attendre à recevoir un ou deux ack. Le MA acquitte toujours, le HA aussi, mais comme il ne sera prévenu (par envoi de binding) qu'en cas de mobilité inter domaine ou de major move, il faut se préparer à parfois ne pas être acquitté par le HA.
Pour savoir exactement où l'on en est, nous utilisons une variable nbBack pour représenter l'état d'attente dans lequel on se trouve.
-1 -> le mobile est en attente d'un seul ack, consécutivement à un micro mouvement. 0 -> aucun ack attendu. 1 -> le mobile est en attente de deux ack après un macro mouvement, le ack du MA est déjà arrivé. 2 -> le mobile est en attente de deux ack après un macro mouvement, le ack du HA est déjà arrivé. 3 -> le mobile est en attente de deux ack après un macro mouvement.D'autre cas viendront enrichir ceux-ci lorsque nous parlerons de changement de mode (cf ).
Dans la souche FreeBSD un paquet contenant une/plusieurs destination option(s), est remonté par le noyau dans le démon ndpd-host. Il est traité dans la fonction recv_destopt, qui dirige le paquet vers d'autres fonctions, recv_bnd_upd ou autre. Dans notre cas, c'est recv_bnd_ack qui nous intéresse. En début de cette fonction nous ajoutons un appel à une de nos fonctions :
si check_uhmma_back(paquet) == 1 alors terminer sinon traiter paquet selon MIP
Notre fonction va analyser le paquet et déduire s'il s'agit d'un ack pour UHMMA ou pour MIP. S'il s'agit d'un ack pour HMIP, il sera traité. La fonction retourne 1 s'il s'agit de HMIP, ainsi recv_bnd_ack saura qu'il ne faut traiter une nouvelle fois ce paquet.
check_uhmma_back
si mode du mobile == MODE2 alors si source du paquet == MA local alors si numéro de séquence du paquet < compteur de séquence alors retourner 1 si status du paquet != accepté alors retourner 1 cas nbBack parmis -1 : lancer hmip_ack 2 : lancer hmip_ack 3 : nbBack <- 1 si numéro de séquence du paquet > compteur de séquence alors compteur de séquence <- numéro de séquence du paquet *1 retourner 1 sinon si source du paquet == HA alors si numéro de séquence du paquet < compteur de séquence alors retourner 1 si status du paquet != accepté alors retourner 1 cas nbBack parmis 3 : nbBack <- 2 1 : lancer hmip_ack retourner 1 sinon retourner 0 sinon si mode du mobile == MODE1 alors si source == MA local alors si numéro de séquence du paquet < compteur de séquence alors retourner 1 si status du paquet != accepté alors retourner 1 lancer hmip_ack retourner 1 sinon retourner 0 sinon retourner 0 fonction hmip_ack stopper reemit_timer sauvegarder MA local dans MA précédent libérer mémoire du paquet d'enregistrement si réseau courant != réseau mère et mode != MIP_MODE alors lancer uMIP_timer avec send_old_position en traitant nbBack <- 0 si numéro de séquence du paquet > compteur de séquence alors compteur de séquence <- numéro de séquence du paquet *1
Cette fonction va par la suite s'enrichir de nouveaux cas relatifs aux changements de mode. Nous les verons dans le paragraphe correspondant (cf. ).
Note : send_old_position lancée ici est définie en 1.3.5.
Nous allons décrire ici comment détecte t'on qu'il faut changer de mode et les mécanismes de changement de mode.
Il est nécessaire de changer de mode dans plusieurs cas. Il est importante de comprendre qu'il existe une hiérarchie dans les modes. MIP est le mode le plus bas, MODE1 est le mode intermédiaire et MODE2 est le mode le plus grand. Lorsque l'utilisateur démarre son mobile, il lui communique son mode de prédilection. Le mobile fera en sorte de toujours utiliser le mode le plus proche dans l'ordre défini ci-dessus. A noter qu'un changement de mode se fait toujours après un mouvement, et avant la résolution de celui-ci.
Raisons de changement de mode :
Nous nous servons de l'option MA lue ou absente dans les router adv. reçus (cf. 1.2) pour détecter si un changement de mode est nécessaire. Cette détection est faire en deux endroits différents.
major_move : cette fonction est divisée en deux. La première partie traite les mouvements depuis le réseau mère vers un réseau visité, l'autre partie traite les mouvements qui rammènent le mobile sur son réseau mère. Dans cette dernière il n'y a pas de changement de mode possible. Le mobile doit simplement se dé enregistrer proprement par rapport à sa dernière position. Le mode de mobilité sur le réseau mère n'a pas d'utilité.
Dans la première partie, avant la conditionnelle nous allons vérifier que le réseau sur lequel nous arrivons possède un MA et si ce MA peut satisfaire le mode désiré par l'utilisateur. Nous voyons ici que ces changements de mode se font toujours vers un mode inférieur. Notons qu'il n'y a pas de code spécifique de changement de mode à réaliser. En effet, nous venons de notre réseau mère, où nous n'avions pas de mobilité. Nous pouvons tout simplement changer le mode de mobilité actuelle et utiliser les procédures habituelles de gestion de mouvements.
si MA local == abscent alors si mode du mobile > MIP alors mode du mobile <- MIP gérer mobilité selon MIP terminer si mobility mode == MODE2 alors si mode du MA == MODE1 alors mode du mobile <- MODE1 augmenter le compteur de séquence envoyer enregistrement au MA gérer mobilité selon MIP terminer sinon augmenter le compteur de séquence envoyer enregistrement au MA terminer si mobility mode == MODE1 alors augmenter le compteur de séquence envoyer enregistrement au MA gérer mobilité selon MIP
minor_move : dans cette fonction nous allons expliquer comment il est possible de changer de mode pour tendre vers le choix de l'utilisateur. A l'opposé de major_move nous allons ici changer de mode vers un mode supérieur. Notre algorithme se place juste avant la conditionnelle que nous avons produite dans 1.2. Il convient également de vérifier si l'on doit changer de mode pour un mode inférieur. On rejoint alors la même forme d'algorithme que pour major_move.
si mode du mobile < mode du MA alors si mode du mobile < mode initial de l'utilisateur alors si mode initial de l'utilisateur > mode du MA alors need_to_swap <- mode du MA sinon need_to_swap <- mode initial de l'utilisateur lancer la fonction swap_mode terminer si mobility mode == MODE2 alors lancer send_uhmma_minor_reg terminer si mobility mode == MODE1 alors lancer send_uhmma_minor_reg gérer la mobilité selon MIPAu contraire de major_move, on vient d'un autre réseau où la mobilité était traitée. Le mobile était donc configuré (variables, adresses, etc.). Nous ne pouvons nous contenter de changer de mode, il faut exécuter du code pour mettre à jour la configuration ; nous utilisons une fonction swap_mode.
send_uhmma_minor_reg : dans la section de cette fonction qui traite des mouvements inter domaine, nous allons ajouter au début du code pour vérifier que le mode désiré par le mobile est disponible. Si ce n'est pas le cas, le mobile change de mode.
si MA local == abscent alors si mode du mobile > MIP alors need_to_swap <- MIP_MODE lancer la fonction swap_mode terminer si mobility mode == MODE2 alors si mode du MA == MODE1 alors need_to_swap <- MODE1 lancer la fonction swap_mode terminer
Trop de ré émissions : une autre façon de déterminer si un changement de mode est nécessaire, est de compter le nombre de ré émissions d'envoi d'enregistrement. Nous avons préciser en 1.1.2 que l'utilisateur pouvait spécifier le nombre de retransmissions maximal qu'il désirait avant que son mobile ne change de mode. Cette décision de changement de mode est faite dans la fonction resend_uhmma_reg, dont nous avons brièvement parlé en 1.3.2.
augmenter nombre de retransmission si nombre de retransmissions >= nombre de retransmissions max alors lancer stop_HMIP terminer incrémenter compteur de séquence incrémenter numéro de séquence dans le paquet sauvegardé renvoyer paquet d'enregistrement relancer timer associé à la ré émission avec resend_uhmma_reg en traitantLa fonction stop_HMIP est décrite en . Il ne faut pas oublier d'initialiser la variable nombre de retransmissions à 0 lorsque l'on envoie le premier paquet d'enregistrement (dans build_send_reg 1.3.2).
Ces mécanismes sont regroupés dans deux fonctions. La première, swap_mode, tient compte du mode de mobilité actuel, et du mode vers lequel on doit changer (contenu dans need_to_swap). En fonction de ces deux paramètres, elle effectue le bon traitement.
swap_mode
cas mode du mobile parmis MIP_MODE : cas need_to_swap parmis MODE1 : mode du mobile <- MODE1 augmenter le compteur de séquence envoyer paquet d'enregistrement au MA local mettre à jour liste des correspondants *1 gérer la mobilité selon MIP (envoi de bindings aux correspondants) MODE2 : nbBack <- 200 *3 copier la nouvelle careof dans le champ prévue à cet effet dans la structure HA mode du mobile <- MODE2_FROM_MIP augmenter le compteur de séquence envoyer paquet d'enregistrement au MA local envoyer liste de correspondants au MA local *2 MODE1 : cas need_to_swap parmis MIP_MODE : nbBack <- 200 *3 copier la nouvelle careof dans le champ prévue à cet effet dans la structure HA mode du mobile <- MODE2_FROM_MIP augmenter le compteur de séquence envoyer paquet d'enregistrement au MA local envoyer liste de correspondants au MA local *2 MODE2 : envoyer forward au MA précédent *5 stopper uMIP_timer, reemit_timer et back_timer effacer adresses de MA, MA précédent et VCOA déprécier la VCOA des interfaces réseau mode du mobile <- MIP_MODE mettre à jour liste des correspondants *1 MODE2 : cas need_to_swap parmis MODE1 : envoyer smooth handoff au MA précédent *4 nbBack <- 21 *3 MIP_MODE : envoyer smooth handoff au MA précédent *4 nbBack <- 20 *3
Commentaires : nous avons repéré certains points déliquats de cet algorithme par des chiffres, nous allons maintenant expliquer ces points sensibles.
stop_HMIP : cette fonction est appelée consécutivement à la détection de trop nombreuses ré émissions d'enregistrement.
nbBACK <- 0 stopper timer associé à la ré émission des enregistrements libérer mémoire occupée par le paquet d'enregistrement si on arrive du réseau mère alors retirer la VCOA des interfaces réseau mode du mobile <- MIP_MODE si mode du mobile == MODE2 alors envoyer une home registration au home agent sinon le mode est MODE1 simuler un minor move en utilisant les procédures de mouvement MIP *1 sinon on arrive d'un autre réseau sauvegarder le mode courant dans old_mode need_to_swap <- MIP_MODE lancer swap_mode *2 si old_mode == MODE1 alors simuler un minor move en utilisant les procédures de mouvement MIP *3
La fin d'une procédure de swap se fait dans la fonction check_uhmma_back, lorsque l'on a reçu les ack escomptés pour valider notre changement de mode. Nous ajoutons donc de nouveaux cas dans cette fonction initialement définie en 1.3.2.
20 -> le mobile est en attente d'un ack du MA précédent suite à un changement de mode MODE2 vers MODE1 et donc un smooth handoff. Ce ack contient une liste de correspondants. 21 -> le mobile est en attente d'un ack du MA précédent suite à un changement de mode MODE2 vers MIP et donc un smooth handoff. Ce ack contient une liste de correspondants. 200 -> le mobile est en attente du ack du MA car il vient de lui envoyer sa liste de correspondants. Nous devons également attendre le ack du HA qui indique que celui-ci a bien enregistré la nouvelle position.L'algorithme suivant est à insérer dans celui défini auparavant, dans le cas parmis de la conditionnelle si mode du mobile == MODE2 alors si source du paquet == MA local alors ...
20 : décoder et stocker liste de correspondants mode du mobile <- MIP_MODE mettre à jour liste de correspondants gérer la mobilité selon MIP compteur de séquence <- 0 effacer les adresses VCOA, MA et MA précédent stopper les timers HMIP libérer le paquets de ré émission déprécier les VCOA des interfaces réseau 21 : décoder et stocker liste de correpondants mode du mobile <- MODE1 si major move alors lancer send_uhmma_major_reg sinon lancer send_uhmma_minor_reg mettre à jour liste de correspondants gérer la mobilité selon MIP si numéro de séquence > compteur de séquence alors compteur de séquence <- numéro de séquence *1 200 : nbBACK <- 100
Plaçons maintenant un nouveau cas dans le cas parmis si source du paquet == HA, et toujours dans le mode MODE2.
200 : 100 : retirer les correspondants de la liste des correspondants lancer hmip_ack
Commentaire : dans le cas de reception du HA, nous prenons en compte deux valeurs : 100, qui signifie que le ack du MA est arrivé, et 200, qui précise que le ack du MA n'est pas encore arrivé. Il est peut être perdu, ou coincé dans une congestion. Nous considérons cependant que la situation est régulière et que le ack du MA n'est pas nécessaire, car si nous avons le ack du HA c'est que le MA a bien reçu la liste, a enregistré le mobile et a envoyé une home registration.
Le changement d'interface est un mouvement. Car le changement de cartes s'accompagne d'un changement d'adresse MAC, donc d'EUI64, donc d'adresse temporaire.
Exemple : un mobile est sur son réseau mère connecté par une interface ethernet. Il change d'interface pour une autre carte, elle aussi connectée sur le réseau mère. Ce changement est un mouvement, le mobile va s'enregistrer auprès de son home agent en utilisant une adresse temporaire composée avec l'EUI64 de la nouvelle carte réseau.
Les mouvements par changement de cartes ne sont pas supportés par les procédures habituelles (major_move et minor_move). Ils sont gérés dans la fonction mobile_chgif. A l'intérieur de cette fonction nous allons apporter des modifications pour prendre en compte la mobilité hiérarchique.
Cette fonction traite plusieurs ca, que nous allons passer en revue :
Le mobile n'a plus d'interface : dans ce cas nous allons détruire les préfixes virtuels que nous sauvegardons dans une liste à part. En effet, si l'interface retirée est déclarée comme "removable", le code de Mobile IPv6 retire toutes les adresses IPv6 de l'interface à l'ejection. Nous devons également nettoyer nos listes d'adresses virtuelles.
Dans la conditionnelle if(def_if == NULL) nous ajoutons
parcourir liste des VCOA retirer VCOA des interfaces retirer VCOA de la liste des VCOANottons que nous procédons au retrait immédiat des préfixes, et non à la dépréciation de ceux-ci.
Le mobile obtient une nouvelle interface : en fin de fonction, les procédures de gestion de mouvement Mobile IPv6 sont appelées. Nous devons ici placer nos conditionnelles pour tenir compte des modes de fonctionnement et des types de mouvements.
Les opérations ne sont pas triviales car il faut tenir compte du fait, que le mouvement peut nous ammener à changer de mode de fonctionnement. Nous allons regarder le mode de fonctionnement actuel. Si ce mode est 1 ou 2, nous allons faire appel à une fonction uhmma_move_mode. Cette fonction va gérer le mouvement en tenant compte d'un changement de mode éventuel. Si le mode actuel est MIP, nous devons exécuter le code de Mobile IPv6 sauf si le mobile désire fonctionner selon un mode 1 ou 2, auquel cas un changement de mode est possible, nous appelons uhmma_move_mode.
mobile_chgif
Cette fonction va nous rendre un résultat qui indique si le code de Mobile IPv6 doit être exécuté ou non. Ce code est en fait la gestion du mouvement pour tous les correspondants.
si mode du mobile == MODE1 ou MODE2 OU (mode du mobile == MIP_MODE ET (mode intial == MODE1 ou MODE2) ) alors si uhmma_move_mode == 0 alors terminer si mode du mobile == MODE2 alors terminer code de Mobile IPv6uhmma_move_mode
si le réseau visité est le réseau mère alors send_uhmma_major_reg retourner 1 si MA précédent == adresse indeterminée alors *1 si MA local == abscent alors mode du mobile <- MIP_MODE retourner 1 si mode du mobile == MODE2 alors si mode du MA == MODE1 alors mode du mobile <- MODE1 lancer send_uhmma_major_reg retourner 1 sinon lancer send_uhmma_major_reg retourner 0 si mode du mobile == MIP_MODE alors lancer send_uhmma_major_reg retourner 1 si mode du mobile == MIP_MODE alors si mode du mobile < mode intial alors si mode initial > mode du MA alors need_to_swap <- mode du MA sinon need_to_swap <- mode initial lancer swap_mode retourner 0 sinon *2 retourner 1 si macro mouvement alors si mode du mobile < mode intial alors si mode initial > mode du MA alors need_to_swap <- mode du MA sinon need_to_swap <- mode initial lancer swap_mode retourner 0 lancer send_uhmma_minor_reg retourner 1
Tout comme pour le mobile, nous utilisons des variables globales et le fichier /etc/gateway6 pour initialiser certaines d'entre elles.
extern char MA_op; /* mode 1 or 2 */ extern char max_retrans; /* number max of smooth retransmissions */ extern char verboseU; /* verbose for UHMMA only */ extern int socket_bpf; /* socket for CN detection */ extern u_char site_len; /* length of the site prefix */ extern u_short charge; /* the charge */ extern struct in6_addr MA_address; /* address on the virtual prefix */ extern struct temp_global temp; /* list of timer's vallues */ extern struct timeout * MA_annonce_timer; /* timer for sending ma annonce */ extern struct Vprefix VirtualNetwork; /* virtual network data */ TAILQ_HEAD(, BaseStation) listBS; /* MA data are sent to this addresses */ TAILQ_HEAD(, MobilityAgent)listMA; /* list of MA on the virtual link */ TAILQ_HEAD( ,mobile) listMH; /* list of managed mobile hosts */ TAILQ_HEAD(, WBACK) waitingBack; /* list for smooth handoff */
Nous utilisons la même méthode que pour le mobile (vue en 1.1.2). Cette méthode nous sert à initialiser :
Pour plus de détails sur la configuration consulter le document [].
Le paquet d'enregistrement d'un mobile contient deux destination options ; un binding update et une home address. Un tel paquet arrivant dans un MA sera remonté par le kernel dans le démon ndpd-router. Là il sera traité dans la fonction recv_destopt. Cette fonction sert à analyser le paquet arrivant et à lancer la fonction adéquate pour son traitement. Jusqu'à présent un paquet contenant une destination option binding update était passé en paramêtre à la fonction recv_bnd_upd. Nous allons devoir identifier les paquets qui sont des enregistrements MHIP et non des binding updates MIPv6, et les traiter dans une nouvelle fonction recv_uhmma_reg.
recv_destopt est composée d'une boucle de décodage des options. Cette boucle parcours le paquet pour traiter toutes les options. Elle est composée d'un cas parmis. Lorsque le type de l'option est un binding update, nous regardons si la taille de cette option est la taille d'un enregistrement HMIP (car un paquet d'enregistrement HMIP fait toujours la même taille). Si cette option correspond, on positionne un flag. Nous ne pouvons pas lancer la fonction de traitement immédiatement, car nous avons besoin de l'option home address, qui se situe quelque part en aval dans la chaine des options.
Lorsque l'on a parcouru toutes les options, on sort de la boucle. C'est à cet instant que l'on utilise l'algorithme ci-dessous :
si flag == 1 alors si machine local est un MA en mode 1 ou 2 alors lancer recv_uhmma_reg sinon envoyer un binding ack à l'émetteur avec status d'erreur
Les mobiles enregistrés sont placés dans une liste. Cette liste contient des enregistrements de type ßtruct mobile", structure définie par MIPv6. Nous y avons réjouter plusieurs champs dont un est la liste des correspondants enregistrés pour le mobile. Un autre de ces champs est une adresse qui contient la VCOA.
fonction recv_uhmma_reg décoder le paquet si les options du paquet contiennent des erreurs alors envoyer binding ack avec message d'erreur parcourir liste des mobiles si le mobile est déjà enregistré dans la liste des mobiles alors si champ lifetime du paquet == 0 alors lancer kill_mobile terminer si numéro de séquence du paquet < numéro de séquence de la liste alors envoyer binding ack à l'émetteur avec erreur terminer si le mobile n'a pas changé de position (care-of) alors si le dernier mouvement était un macro move alors *1 si le mobile est géré en mode 2 alors *2 envoyer binding update au home agent du mobile envoyer binding ack au mobile sinon le mobile a changé de position détruire le tug vers l'ancienne position du mobile ouvrir un tug vers la nouvelle position du mobile sauvegarder la nouvelle position du mobile dans la liste des mobiles relancer le timer du mobile avec la durée lifetime du paquet et le traitant kill_mobile si le mobile vient de retourner sur son réseau mère alors *3 si le mobile est géré en mode 2 alors numéro de séquence du HA <- numéro de séquence du paquet *4 envoyer binding update (H@/H@) à tous les correspondants retirer les correspondants de la liste des correspondants du mobile sinon le mobile vient d'effectuer un micro move si le mobile est géré en mode 2 alors envoyer binding update à tous les correspondants locaux (sauf au HA) avec la nouvelle position du mobile envoyer binding ack avec status accepté au mobile sinon le mobile n'est pas enregistré dans la liste des mobiles si flags du paquet == MODE2 alors si le MA ne tourne pas en mode MODE2 alors envoyer binding ack à l'expéditeur avec erreur terminer créer enregistrement du mobile dans la liste des mobiles construire VCOA pour le mobile créer un tug vers le mobile créer un proxy entre VCOA et position du mobile *5 si le mobile vient de son réseau mère alors *6 si le mobile demande un enregistrement en mode 2 alors créer l'enregistrement du HA dans liste des correspondants du mobile envoyer home registration au HA avec VCOA sinon le mobile vient d'un autre réseau si le mobile est géré en mode 1 alors envoyer forward request au MA du réseau précédent *7 sinon le mobile est géré en mode 2 envoyer smooth handoff au MA du réseau précédent *8 terminer si flags du paquet != MODE2_FROM_MIP alors *9 envoyer binding ack au mobile lancer un timer de durée lifetime du paquet avec kill_mobile en traitant
kill_mobile : nous utilisons cette fonction pour retirer un mobile de la liste des mobiles.
si il existe des correspondants dans la liste des correspondants alors lancer kill_cn_list stopper timer associé au mobile fermer le tug vers le mobile si il existe une procédure de smooth handoff en cours pour ce mobile alors stopper timer de ré émission libérer mémoire pour stocker le paquet de smooth handoff retirer le mobile de la liste des mobileNous verrons en détails la fonction kill_cn_list dans le paragraphe sur la gestion des correspondants (cf. ).
Le maintien de position est un paquet envoyé régulièrement par le mobile pour confirmer qu'il est toujours à sa position. Chaque mobile enregistré est associé à un timer qui lance le traitant kill_mobile s'il vient à expirer. Un paquet de maintien de position relance le timer du mobile, prolongeant ainsi sa durée de vie.
Le paquet de maintien de position est un binding update identique à celui de MIPv6 excepté qu'il contient le flag OLD_POSITION_FLAG. L'arrivée d'un tel paquet sera donc dans recv_destopt. Nous allons ajouter un test devant l'appel de recv_home_reg et recv_bnd_upd.
si flag du paquet == OLD_POSITION_FLAG alors si MA local tourne en mode 1 ou 2 alors lancer recv_old_position sinon envoyer binding ack à l'expéditeur avec status d'erreur terminer si flag du paquet == OPT6_BNDU_HR alors lancer recv_home_reg sinon lancer recv_bnd_upd
recv_old_position : cette fonction vérifie que le mobile expéditeur est effectivement dans la liste des mobiles. Si ce n'est pas le cas, elle renvoie un binding ack à cet expéditeur avec le code erreur correspondant.
Si le mobile est enregistré, il faut vérifier que le numéro de séquence du paquet est supérieur au numéro de séquence de la liste. Si ce n'est pas le cas, on retourne un binding ack avec status d'erreur approprié.
Enfin, si tout est correct, la fonction relance le timer associé au mobile et met à jour le numéro de séquence dans la liste.
Le smooth handoof est le protocole utilisé entre deux MA ou entre un MA et un mobile pour transférer une liste de correspondants après un mouvement inter domaine.
L'envoi d'un smooth handoff est provoqué par l'arrivé d'un enregistrement d'un mobile venant d'un autre domaine (cf. 2.2.2). Le smooth handoff est en fait un paquet binding update comme définit dans MIP sauf que le flag est : SMOOTH_FLAG. L'envoi d'un smooth handoff se résume en trois points :
garder une trace de l'envoi du smooth handoff. Un MA peut être amené à gérer plusieurs smooth handoff en même temps. Lorsque les réponses arrivent, il faut associer la réponse avec la demande correspondante. Pour cela nous utilisons une liste de ßtruct WBACK". Cette structure contient les informations suivantes :
Lorsque le MA envoie un smooth handoff, il créait et ajoute un enregistrement dans cette liste. Nous verrons comment ces enregistrements sont utilisés lors de la réception d'une liste de correspondants en .
Un smooth handoff est un binding update avec un champ flag particulier. Il sera donc intercepté dans la fonction recv_destopt. Nous avons déjà parlé de cette fonction et son algorithme devient maintenant :
si flag du paquet == OLD_POSITION_FLAG alors si MA local tourne en mode 1 ou 2 alors lancer recv_old_position sinon envoyer binding ack à l'expéditeur avec status d'erreur terminer si flag du paquet == SMOOTH_FLAG alors si MA local tourne en mode 2 alors lancer recv_smooth sinon envoyer binding ack à l'expéditeur avec status d'erreur terminer si flag du paquet == OPT6_BNDU_HR alors lancer recv_home_reg sinon lancer recv_bnd_upd
recv_smooth : cette fonction va prendre en charge le transfert de la liste d'un mobile anciennement situé dans le domaine.
si mobile est enregistré dans la liste des mobiles alors si numéro de séquence du paquet < numéro de séquence dans la liste alors envoyer binding ack avec status d'erreur correspondant sinon sauvegarder numéro de séquence du paquet dans la liste si aucun smooth handoff pour ce mobile n'est déjà parvenu alors *1 fermer le tug vers l'anciennce position du mobile mettre à jour la position du mobile dans la liste ouvrir tug vers nouvelle position du mobile relancer timer associé au mobile avec lifetime en durée et kill_mobile en traitant lancer send_cn_list si le mobile est géré en mode 2 alors stopper l'envoi de binding pour tous les correspondants du mobile *2 sinon le mobile n'est pas enregistré envoyer binding ack avec status d'erreur correspondant à l'expéditeurNotez que la source du smooth handoff peut être un MA, mais aussi un mobile qui vient de changer de mode. Le MA récepteur ne fait aucune différence de traitement entre les deux. Le status d'erreur est OPT6_BNDA_CN_LIST_KO, celui de réussite OPT6_BNDA_CN_LIST_OK.
send_cn_list : cette fonction est utiliser pour envoyer la liste des correspondants.
compter le nombre de correspondants calculer la taille du paquet à émettre construire le paquet envoyer le paquetLe paquet est un binding ack avec une sub-option contenant la liste des correspondants. La construction de la liste se fait par concaténation d'enregistrements contenant les informations sur les correspondants. Ce ne sont pas les struct corr que nous concaténons. Ces structures contiennent des informations (comme des pointeurs, des timers, etc.) qu'il n'est pas pertinent de transférer. Aussi nous créons notre propre structure pour le transfert.
Nous avons vu que cette liste est contenue dans un binding ack. Elle passera donc par recv_destopt et sera finalement traitée dans recv_bnd_ack. Dans cette fonction nous allons ajouter un petit test : si le status du ack est OPT6_BNDA_CN_LIST_KO ou OPT6_BNDA_CN_LIST_OK alors lancer recv_cn_list. Attention il s'agit de la fonction recv_bnd_ack employé dans ndpd-router, donc celle qui est codée dans mh-dummy.c
recv_cn_list :
si le status du paquet == OPT6_BNDA_CN_LIST_KO alors parcourir la liste des WBACK *1 si l'enregistrement est dans la liste alors stopper le timer de ré émission du smooth handoff associé sauvegarder le numéro de séquence du paquet dans la liste des mobiles envoyer binding ack avec status refusé au mobile lancer kill_mobile retirer la structure WBACK de la liste sinon le status est OPT6_BNDA_CN_LIST_OK parcourir la liste des WBACK *1 si l'enregistrement est dans la liste alors stopper le timer de ré émission du smooth handoff associé sauvegarder le numéro de séquence du paquet dans la liste des mobiles lancer store_list envoyer des binding updates aux correspondants *3 envoyer binding ack avec status accepté au mobile retirer la structure WBACK de la liste sinon l'enregistrement n'est pas dans la liste parcourir liste des mobiles *2 si le mobile figure dans la liste alors lancer store_list envoyer des binding updates aux correspondants *3 relancer timer associé au mobile avec lifetime du paquet en durée et kill_mobile en traitant envoyer binding ack au mobile avec status accepté
Le protocole de forward est une version allégée du smooth handoff. Il ne transfert aucune liste et se contente de mettre en place un mécanisme de suivi des paquets depuis une ancienne position vers une nouvelle.
Nous avons vu que le lancement d'un forward se faisait dans recv_uhmma_reg. Un forward est un paquet identique à celui d'un smooth handoff (et donc à un binding update) avec le flag contenant : FORWARD_FLAG. Ceci nous ajoute un nouveau cas dans notre fonction recv_destopt.
Nous ne détaillons pas l'envoi d'un forward, car il s'agit d'un smooth handoff sans la mécanique de retransmission (simple donc :-).
Réception
si flag du paquet == OLD_POSITION_FLAG alors si MA local tourne en mode 1 ou 2 alors lancer recv_old_position sinon envoyer binding ack à l'expéditeur avec status d'erreur terminer si flag du paquet == SMOOTH_FLAG alors si MA local tourne en mode 2 alors lancer recv_smooth sinon envoyer binding ack à l'expéditeur avec status d'erreur terminer si flag du paquet == FORWARD_FLAG alors si MA local tourne en mode 2 alors lancer recv_forward sinon envoyer binding ack à l'expéditeur avec status d'erreur terminer si flag du paquet == OPT6_BNDU_HR alors lancer recv_home_reg sinon lancer recv_bnd_updIl n'y a aucun mécanisme de retransmission et d'acquittement pour le forward. Si le protocole échoue, il en résultera la perte des hypothétiques paquets transmis par les correspondants vers l'ancienne position du mobile avant que ceux-ci n'aient reçu un nouveau binding update avec la nouvelle position.
recv_forward
si mobile est enregistré dans la liste des mobiles alors si numéro de séquence du paquet < numéro de séquence dans la liste alors envoyer binding ack avec status d'erreur correspondant sinon sauvegarder numéro de séquence du paquet dans la liste fermer le tug vers l'anciennce position du mobile mettre à jour la position du mobile dans la liste ouvrir tug vers nouvelle position du mobile relancer timer associé au mobile avec lifetime en durée et kill_mobile en traitant sinon le mobile n'est pas enregistré envoyer binding ack avec status d'erreur correspondant à l'expéditeur
Tout cette partie est relative au mode 2 uniquement.
Les mobiles sont chainés dans une liste de struct mobile, structure définie dans MIP. Nous y avons ajouté un nouveau champ ; une liste de struct corr (également définie dans MIP) pour stocker les correspondants enregistrés de ce mobile. Cette liste contient au minimum un enregistrement, qui est le home agent.
listMH | v ------- ------- ------- | MH1 |-->| MH2 |-->| MH3 |--> NULL ------- ------- ------- | | | V V V ------- ------- ------- | HA | | HA | | HA | ------- ------- ------- | | | V V V ------- ------- | CH1 | NULL | CH1 | ------- ------- | | V V ------- | CH2 | NULL ------- | V NULLNous avons ajouté un nouveau champ à la structure corr, le champ VCOA, qui contient la VCOA du mobile.
La détection de nouveaux correspondants pour un mobile enregistré est simple. Un correspondant non enregistré est un correspondant qui n'a connaissance de la position d'un mobile. Il va donc envoyer les premiers paquets vers la H@ et ceux-ci seront interceptés par le HA, puis forwardés vers la VCOA. Le MA va également rediriger ces paquets vers la PCOA. Au passage le MA peux détecter le correspondant en utilisant un simple BPF. Le filtre de ce BPF portera sur le champ "next header" de l'entête IPv6. Si celui-ci est la valeur qui correspondant à IPv6, il s'agit d'un paquet encapsulé. Il suffit maintenant de vérifier si le mobile (identifié par le champ destination du paquet encapsulé qui contient la H@) est enregistré en mode 2 dans la liste des mobiles. Si tel est le cas, il suffit d'envoyer un binding update à ce correspondant et de l'enregistrer dans la liste des correspondants du mobile. Nous verrons en qu'il faut utiliser le champ type du correspondant pour identifier le type de care-fo à envoyer au correspondant. Nous devons comparer l'adresse du correspondant avec la PCOA du mobile. S'ils sont dans le même domaine, il faudra envoyer la PCOA, la VCOA sinon.
Le BPF est ouvert dans la procédure d'initialisation du MA, si et seulement si celui-ci est lancé en mode 2. Le BPF sert pour la détection des correspondants de TOUS les mobiles enregistrés. Il est ouvert sur une socket. La boucle principale de ndpd-router scrute si des données arrivent dans les sockets ICMP, ROUTE et DESTINATION OPTION. Si des données arrivent sur une de ces sockets, la fonction correspondantes est appelée pour gérer l'événement. Nous allons ajouter un nouveau test sur notre socket BPF. Si des données arrivent, nous lancerons recv_bpf.
recv_bpf
lire les données arrivant dans la socket bpf parcourir liste des mobiles si le destinataire est dans la liste alors si le mobile est géré en mode 2 parcourir la liste des correspondants du mobile si l'expéditeur n'est pas dans la liste alors ajouter correspondant dans la liste des correpondants si le correspondant est dans le domaine alors le type de correspondant est NO_VCOA_NEEDED sinon le type de correspondant est VCOA_NEEDED envoyer un binding update à ce correspondant
Nous avons copié les fonctions d'envoi des binding updates par le mobile pour en faire nos fonctions pour notre MA. La grande différence avec le code MIP, est que nous allons devoir inclure la care-of dans les options destination.
Lorsque nous envoyons un binding update à la place d'un mobile, nous devons savoir quelle COA mettre dans le paquet ; la VCOA ou la PCOA. Nous utilisons le champ type de la structure corr pour contenir une information qui va renseigner send_bnd_upd sur la COA à insérer ; le champ type.
Envoi : le code d'envoi est identique à celui d'un mobile à l'exception de la composition du binding update qui doit inclure un champ care-of et d'un test sur la variable type, qui conditionne l'adresse à copier dans le champ care-of. Notons que le home agent est géré par une fonction spécifique send_home_reg. Le HA doit obligatoirement recevoir la VCOA (sauf en cas de retour sur réseau mère). Le type d'un HA ne peut donc être NO_VCOA_NEEDED.
Un binding update doit être envoyé régulièrement au correspondant pour rafraichir le cache d'association. Nous avons mis en place un mécanisme de cadencement directement inclu dans la fonction send_bnd_upd. En fin de fonction, on regarde si le timer associé au correspondant existe, si oui on le relance avec en traitant send_bnd_upd elle même, si non on le lance pour la première fois. C'est ce mécanisme qui doit être stoppé lors de la réception d'un smooth handoff ou d'un forward. Il est stoppé par destruction de ces timers.
fonction send_bnd_upd construire paquet binding update avec champ care-of vide cas type du correpondant parmis VCOA_NEEDED : copier la VCOA dans le champ care-of NO_VCOA_NEEDED : copier la PCOA dans le champ care-of HOME_NEEDED : copier la H@ dans le champ care-of envoyer paquet au correspondant si timer associé au correspondant existe alors relancer timer avec send_bnd_upd en traitant sinon lancer timer avec send_bnd_upd en traitantLa durée du timer est calculée en soustrayant 15 secondes au champ lifetime de la structure correspondant. Ce champ est lui même initialisé en copiant la valeur lifetime que le mobile communique dans ses paquets d'enregistrement / maintien de position. Les 15 secondes permettent d'éviter que le correspondant n'envoie de binding request, car le mobile en mode 2 ne sait pas les gérer. Un test est fait pour vérifier que lifetime - 15 est bien supérieur strictement à zéro, si cela n'est pas le cas, le timer est lancé avec un temps de 3 secondes.
Type de care-of : nous venons de voir que send_bnd_upd utilise le type du correspondant pour savoir quelle care-of utiliser. L'initialisation de ce champ est faite lorsque l'on place le correspondant pour la première fois dans la liste des correspondants, càd lorsque l'on reçoit une liste de correspondants après un smooth handoff 2.3.3 ou lorsque l'on détecte un nouveau correspondant 2.5.1. Cette liste sera ensuite mise à jour après chaque mouvement.
Le type du correspondant s'obtient par comparaison du préfixe de l'adresse du correspondant avec celui de la PCOA du mobile. S'ils sont identiques, le correspondant et le mobile sont dans le même domaine. Le type du correspondant est donc NO_VCOA_NEEDED, sinon il est VCOA_NEEDED.
Acknowledgement : le draft Mobile IPv6 précise que dans l'envoi des home registrations, le flag A ßhould be set". Dans notre cas (MODE2) ce flag n'est utile que pour le premier enregistrement après un mouvement. Ensuite pour les confirmations que le MA envoie, ce flag n'est pas souhaitable car il provoque le renvoi d'un ack. Ce ack le mobile ne sera pas quoi en faire (le mobile est en attente de ack seulement après ses mouvements).
Nous allons donc mettre en place un petit protocole pour éviter les ack inutiles :
Les mobiles arrivant dans le domaine apprennent l'adresse du MA en parcourant les rt adv. Ce sont les Base stations qui ajoutent cette adresse dans leur rt adv.
Chaque MA va comptabiliser le nombre de mobile qu'il gère. Un mobile en mode 1 équivaut à un point et un mobile en mode 2 à trois points. La charge est initialisée à zéro dans la procédure d'initialisation du MA. Le calcul de cette somme est donc fait chaque fois que :
si le mobile est déjà enregistré alors charge inchangé sinon le mobile arrive dans le domaine si le mobile arrive de son réseau mère alors si flag == MODE1 alors charge <- charge +1 sinon flag == MODE2 alors charge <- charge +3 sinon le mobile arrive d'un autre domaine si flag == MODE1 alors charge <- charge +1
si status == OPT6_BNDA_CN_LIST_KO alors charge <- charge +1 sinon status == OPT6_BNDA_CN_LIST_OK si le mobile est dans la liste des WBACK alors charge <- charge +3 sinon si le mobile est dans la liste des mobiles alors charge inchangée
Chaque fois que la charge est modifiée, nous faisons appel à une fonction update_MA que nous définissons ci-dessous.
Le MA va ensuite utiliser une nouvelle option des rt adv pour insérer son adresse et sa charge dans ses rt adv. Chaque MA du lien pourra donc construire une liste de MA avec la charge associée.
recv_icmp ; c'est dans cette fonction de ndpd-routeur que nous allons ajouter cette nouvelle option, dans send_rtadv, et la traiter dans recv_rtadv. Cette option, ND_OPT_CH est composée d'un entier sur 16 bits pour la charge, et d'une adresse IPv6. L'insertion est simple, la reception est faite en ajoutant un cas dans le cas parmis de recv_rtadv. Nous décodons la charge et l'adresse et faisons appel à une fonction update_MA.
update_MA : cette fonction va gérer la liste des MA. On lui donne un MA en paramètre. La liste des MA est une nouvelle liste globale. Lorsqu'un MA est nouveau, on l'ajoute dans la liste en le plaçant de façon à ce que la liste soit triée dans l'ordre du moins chargé vers le plus chargé. Si le MA est déjà dans la liste, on vérifie si sa charge a changé, et si besoin on le déplace dans la liste. A chaque MA nous associons un timer, qui nous servira à retirer un MA s'il ne s'est plus manifesté depuis un temps déterminé.
Notez que dans la procédure d'intialisation du MA, nous devons ajouter un enregistrement correspondant au MA local.
parcourir liste des MA si le MA est dans la liste alors relancer timer associé au MA avec kill_MA en traitant si nouvelle charge != ancienne charge connue alors retirer MA de la liste insérer le MA dans la liste sauvegarder nouvelle charge dans liste des MA sinon le MA n'est pas la liste créer enregistrement pour le MA lancer un timer associé au MA avec kill_MA en traitant insérer le MA dans la liste des MAkill_mobile est une petit fonction qui retire un MA de la liste et libère sa structure.
Le MA envoie un paquet contenant son adresse et son mode de fonctionnement à une série de base stations. Cette liste est déterminée par l'administrateur lorsqu'il lance le MA. Les adresses sont entrées dans le fichier de configuration. Pour l'instant nous utiilisons un paquet avec une destination option BREQ. Mais nous comptons utiliser un binding update. L'envoi de ce paquet est faite de façon régulière. Nous utilisons donc un timer, que nous lançons pour la première fois dans la procédure d'initialisation du MA. Nous n'envoyons pas dès le boot un paquet, nous attendons quelques secondes, pour que le MA est fini sa procédure de boot (adresse, rt adv., etc.). Ensuite la fonction utilisée comme traitant procédera à l'envoi du paquet, puis relancera le timer avec elle même en traitant. Ce processus continue jusqu'à l'arrêt du MA.
Lorsque la fonction d'envoi d'annonce démarre elle consulte le premier enregistrement de la liste des MA, si et seulement si le MA local est le premier de la liste il faut envoyer une annonce de MA aux BS.
Lorsque l'on stoppe le MA, la fonction uhmma_ma_cleanup émet une dernière annonce vers les stations de base en précisant l'adresse indéterminée. Ainsi, les stations de base n'ajoutent plus d'option MA address dans les rt adv.
1déprécier ne signifie pas retirer immédiatement, mais équivaut à lancer un timer pour une durée donnée. Au bout de cette durée, l'adresse sera effectivement retirée.
2dans le source de ndpd-host nous trouvons une gestion de timer opérationnelle. Nous avons donc utilisé les fonctions du fichier util.c. Pour schématiser, la boucle préincipale de ndpd-host regarde à chaque passage si un timer vient d'expirer, si oui elle lance le traitant associé. Nous avons à notre disposition des fonctions pour créer, ajouter, retirer des timers.