Groupe de travail Réseau	J. Romkey	
Request for Comments : 1055	juin l988	
STD 47	Traduction Claude Brière de l’Isle	

NON NORME POUR LA TRANSMISSION DES DATAGRAMMES IP SUR DES LIGNES EN SÉRIE : SLIP

INTRODUCTION

La famille de protocoles TCP/IP fonctionne sur divers supports de réseau : des LAN IEEE 802.3 (ethernet) et 802.5 (anneau à jetons), des lignes X.25, des liaisons par satellite, et des lignes en série. Il y a des encapsulations standard pour les paquets IP définis pour beaucoup de ces réseaux mais il n’y a pas de normes pour les lignes en série. SLIP, Serial Line IP, est actuellement un standard de fait, utilisé communément pour les connexions en série point à point fonctionnant avec TCP/IP. Ce n’est pas une norme de l’Internet (NDT : en fait ce document est devenu la norme n° 47). La distribution du présent mémoire n’est soumise à aucune restriction.

HISTORIQUE

SLIP a son origine dans la mise en œuvre TCP/IP UNET de 3COM du début des années 1980. C’est simplement un protocole de tramage de paquet: SLIP définit une séquence de caractères qui trament les paquets IP sur une ligne en série, et rien de plus. Il ne fournit pas d’adressage, d’identification de type de paquet, de détection/correction d’erreur ou de mécanisme de compression. Parce que le protocole en fait si peu, il est habituellement très facile à mettre en œuvre.

Aux alentours de 1984, Rick Adams l’a mis en œuvre SLIP pour les stations de travail Unix Berkeley 4.2 et Microsystems Sun et la livré au public. Il a été rapidement considéré comme une façon facile et fiable de connecter les hôtes et routeurs TCP/IP aux lignes en série.

SLIP est communément utilisé sur des liaisons spécialisées en série et parfois pour des services à numérotation, et il est habituellement utilisé avec des vitesses de ligne entre 1200 bit/s et 19,2 Kbit/s. Il est utile pour les communications entre des mélanges d’hôtes et de routeurs (hôte à hôte, hôte à routeur et routeur à routeur sont toutes des configurations de réseau courantes de SLIP).

DISPONIBILITÉ

SLIP est disponible pour la plupart des systèmes fondés sur UNIX Berkeley. Il est inclus dans la version standard 4.3BSD de Berkeley. SLIP est disponible pour Ultrix, Sun UNIX et la plupart des autres systèmes UNIX dérivés de Berkeley. Certains concentrateurs de terminaux et les mises en œuvre de PC IBM le prennent aussi en charge.

SLIP pour Berkeley UNIX est disponible via FTP anonyme à uunet.uu.net dans pub/sl.shar.Z. Assurez vous de transférer le fichier en mode binaire puis faites le fonctionner avec le programme UNIX non compressé. Prenez le fichier résultant et utilisez le comme coquille d’écriture pour le programme UNIX /bin/sh (par exemple, /bin/sh sl.shar).

PROTOCOLE

Le protocole SLIP définit deux caractères spéciaux : END et ESC. END est octal 300 (192 en décimal) et ESC est octal 333 (219 en décimal) à ne pas confondre avec le caractère ASCII ESCape ; pour les besoins de cet exposé, ESC indiquera le caractère SLIP ESC. Pour envoyer un paquet, un hôte SLIP commence simplement par envoyer les données dans le paquet. Si un octet de données a le même code que le caractère END, on envoie à la place une séquence de deux octets de ESC et octal 334 (220 en décimal). Si c’est le même code qu’un caractère ESC, on envoie à la place une séquence de deux octets de ESC et octal 335 (221 en décimal). Lorsque le dernier octet du paquet a été envoyé, un caractère END est alors transmis.

Phil Karn suggère un simple changement à l’algorithme, qui est de commencer comme les paquets de fin par un caractère END. Cela va vider tous les octets erronés qui ont été causés par le bruit de ligne. Dans le cas normal, le receveur verra simplement deux caractères END dos à dos, qui vont générer un mauvais paquet IP. Si la mise en œuvre SLIP n’élimine pas le paquet IP de longueur zéro, la mise en œuvre IP le fera certainement. Si il y avait du bruit de ligne, les données reçues à cause de ce bruit seront éliminées sans affecter le paquet suivant.

Comme il n’y a pas de spécification SLIP 'standard', il n’y a pas de taille maximum de paquet réellement définie pour SLIP. Le mieux est probablement d’accepter la taille maximum de paquet utilisée par les pilotes SLIP du Berkeley UNIX : 1006 octets y compris les en-têtes des protocoles IP et de transport (non inclus les caractères de tramage). Donc, toute nouvelle mise en œuvre de SLIP devrait être prête à accepter des datagrammes de 1006 octets et ne devrait pas envoyer plus de 1006 octets dans un datagramme.

FAIBLESSES

Il y a plusieurs dispositions que de nombreux utilisateurs aimeraient que SLIP fournisse et qu’il ne fournit pas. En toute honnêteté, SLIP est juste un protocole très simple conçu il y a assez longtemps alors que ces problèmes n’avaient pas vraiment d’importance. Ce qui suit est ce qui est généralement perçu comme des faiblesses du protocole SLIP existant :

- adressage :
les deux ordinateurs d’une liaison SLIP ont besoin de connaître leurs adresses IP réciproques pour les besoins de l’acheminement. Aussi, lorsqu’on utilise SLIP pour que des hôtes fassent le numéro d’un routeur, le schéma d’adressage peut être assez dynamique et le routeur peut avoir besoin d’informer l’hôte qui numérote de l’adresse IP de l’hôte. SLIP ne fournit actuellement aucun mécanisme pour que les hôtes communiquent des informations d’adressage sur une connexion SLIP.

- identification de type : SLIP n’a pas de champ type. Et donc, un seul protocole peut fonctionner sur une connexion SLIP, aussi dans une configuration de deux ordinateurs DEC fonctionnant tous deux avec TCP/IP et DECnet, il n’y a pas d’espoir de voir TCP/IP et DECnet partager une ligne en série entre eux en utilisant SLIP. Alors que SLIP est "IP pour lignes en série", si une ligne en série connecte deux ordinateurs multi-protocoles, ces ordinateurs devraient être capables d’utiliser plus d’un protocole sur la ligne.

- détection/correction d’erreur :
Sur les lignes téléphoniques, le bruit corrompt les paquets en transit. À cause de la faible vitesse de la ligne (vraisemblablement 2 400 bauds), la retransmission d’un paquet est très coûteuse. La détection d’erreurs n’est pas absolument nécessaire au niveau de SLIP parce que toute application IP devrait détecter les paquets  endommagés (l’en-tête IP et les sommes de contrôle UDP et TCP devraient suffire), bien que certaines applications courantes comme NFS ignorent habituellement la somme de contrôle et dépendent du support réseau pour détecter les paquets endommagés. Parce que la retransmission d’un paquet corrompu par le bruit de ligne prend tellement de temps, ce serait efficace que SLIP puisse fournir de lui-même une sorte de mécanisme simple de correction d’erreur.

- compression :
À cause de la lenteur des lignes téléphoniques (habituellement 2 400 bauds), la compression de paquet causerait de fortes améliorations au débit de paquets. En général, les flux de paquets sur une seule connexion TCP ont peu de champs modifiés dans les en-têtes IP et TCP, aussi des algorithmes simples de compression pourrait envoyer seulement les parties changées des en-têtes au lieu des en-têtes complets.

Divers groupes sont en train de travailler à la conception et la mise en œuvre d’un successeur de SLIP qui va traiter tout ou partie de ces problèmes.

PILOTES SLIP

Les fonctions suivantes en langage C envoient et reçoivent les paquets SLIP. Elles dépendent de deux fonctions, send_char() et recv_char(), qui envoient et reçoivent un seul caractère sur la ligne en série.

/* Codes de caractère spécial SLIP. */
#define END	0300	/* indique la fin du paquet */	
#define ESC	0333	/* indique le bourrage d’octet */	
#define ESC_END	0334	/* ESC ESC_END signifie l’octet de données END */	
#define ESC_ESC	0335	/* ESC ESC_ESC signifie l’octet de données ESC */	

/* SEND_PACKET : envoie un paquet de longueur "len", qui commence à la localisation "p". */
void send_packet(p, len)
	char *p;	
	int len; {	

/* envoie un caractère END initial pour vider toutes données qui pourraient s’être accumulés chez le receveur
* à cause du bruit de ligne. */
	send_char(END);

/* pour chaque octet du paquet, envoyer la séquence de caractères appropriée */
	while(len--) {
		switch(*p) {
                   /* si c'est le même code qu’un caractère END, envoyer un code spécial de deux caractères de façon que 
                    * le receveur ne puisse pas le confondre avec un END. */
	case END:
		send_char(ESC);
		send_char(ESC_END);
		break;

                   /*si c'est le même code qu’un caractère ESC, envoyer un code spécial de deux caractères de façon que 
                    * le receveur ne puisse pas le confondre avec un ESC. */
	case ESC:
		send_char(ESC);
		send_char(ESC_ESC);
		break;

                   /* autrement, envoyer juste le caractère */
	default:
		send_char(*p);
		}

	p++;
	}

           /* dire au receveur que l’envoi du paquet est terminé */
	send_char(END);
	}

/* RECV_PACKET : reçoit un paquet dans la mémoire tampon localisée à "p".
* Si on reçoit plus d’un octet de longueur, le paquet sera tronqué.
* Retourne le nombre d’octets mémorisé dans la mémoire tampon. */
int recv_packet(p, len)
	char *p;
	int len; {
	char c;
	int received = 0;

           /* se poser dans des octets de lecture de boucle jusqu’à l’assemblage d’un paquet complet.
            * S’assurer de ne pas les copier dans le paquet si on manque de place. */
	while(1) {
                   /* obtient un caractère à traiter */
		c = recv_char();

                   /* traite si nécessaire le bourrage d’octet */
		switch(c) {

                   /* si c'est un caractère END, c’est est fini avec le paquet. */
		case END:
                           /* optimisation mineure : si il n’y a pas de données dans le paquet, l’ignorer.
                            * Ceci est destiné à éviter d’encombrer IP avec tous les paquets vides générés par la duplication 
                            * des caractères END qui sont envoyés tour à tour pour essayer de détecter le bruit de ligne. */
		if(received)
			return received;
		else
			break;

                   /* si c'est le même code qu’un caractère ESC, attendre et obtenir un autre caractère et en déduire 
                    * ce qu’il convient de mémoriser du paquet sur cette base.
                    */
		case ESC:
			c = recv_char();

                           /* si "c" n’est pas un de ces deux, c’est une violation du protocole. Le meilleur pari. semble être de
                            * laisser l’octet seul et de le fourrer dans le paquet. */
		switch(c) {
		case ESC_END:
			c = END;
			break;
		case ESC_ESC:
			c = ESC;
			break;
			}

                   /* on tombe ici dans le traitement par défaut et on le laisse mémoriser le caractère pour nous */
		default:
		if(received < len)
			p[received++] = c;
		}
	}
}