My Project
Chargement...
Recherche...
Aucune correspondance
virtio-net.c
Aller à la documentation de ce fichier.
6#include <manux/virtio-net.h>
7#include <manux/memoire.h> // allouerPages
8#include <manux/intel-8259a.h> // pour les interruptions
9#include <manux/pci.h> // Pour aller récupérer l'irq, on doit
10 // pouvoir s'en passer avec une
11 // fonction dans virtio
12#include <manux/io.h> // outb
13#include <manux/debug.h>
14#include <manux/errno.h>
15#ifdef MANUX_RESEAU // Est-ce que ça a vraiment du sens ?
16# include <manux/reseau.h>
17#endif
18#ifdef MANUX_BUFFER_RESEAU // Idem ? (un peu plus, à la limite)
19# include <manux/buffer-reseau.h>
20#endif
21
22// La taille des buffers utilisés par virtio réseau
23#ifndef VIRTIO_TAILLE_TRAME_MAX
24# define VIRTIO_TAILLE_TRAME_MAX 2000
25#endif
26
27#define VR_FILE_RECEPTION 0
28#define VR_FILE_EMISSION 1
29
33#define VIRTIO_NET_F_CSUM 0x00000001 // 0
34#define VIRTIO_NET_F_GUEST_CSUM 0x00000002 // 1
35#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 0x00000004 // 2
36#define VIRTIO_NET_F_MAC 0x00000020 // 5
37#define VIRTIO_NET_F_GUEST_TSO4 0x00000080 // 7
38#define VIRTIO_NET_F_GUEST_TSO6 0x00000100 // 8
39#define VIRTIO_NET_F_GUEST_ECN 0x00000200 // 9
40#define VIRTIO_NET_F_GUEST_UFO 0x00000400 // 10
41#define VIRTIO_NET_F_HOST_TSO4 0x00000800 // 11
42#define VIRTIO_NET_F_HOST_TSO6 0x00001000 // 12
43#define VIRTIO_NET_F_HOST_ECN 0x00002000 // 13
44#define VIRTIO_NET_F_HOST_UFO 0x00004000 // 14
45// Le pilote sait fusionner les buffers
46#define VIRTIO_NET_F_MRG_RXBUF 0x00008000 // 15
47#define VIRTIO_NET_F_STATUS 0x00010000 // 16
48#define VIRTIO_NET_F_CTRL_VQ 0x00020000 // 17
49#define VIRTIO_NET_F_CTRL_RX 0x00040000 // 18
50#define VIRTIO_NET_F_CTRL_VLAN 0x00080000 // 19
51#define VIRTIO_NET_F_GUEST_ANNOUNCE 0x00200000
52
56typedef struct VirtioReseau_t {
59 // Les éléments ci dessous sont sûrement à mettre dans une
60 // structure liée au réseau
63
67typedef struct __attribute__((__packed__)) _VirtioReseauEntete {
68 uint8_t flags;
69 uint8_t typeGSO;
70 uint16_t longueurEntete;
71 uint16_t tailleGSO;
72 uint16_t debutSommeControle;
73 uint16_t decalageSommeControle;
74 //uint16_t nombreBuffers; (si on gère VIRTIO_NET_F_MRG_RXBUF)
76
81
86
88 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff,
89 0xee, 0xde, 0xad, 0xbe, 0x08, 0x06, 0x00, 0x01,
90 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xc0, 0xff,
91 0xee, 0xde, 0xad, 0xbe, 0x0a, 0x00, 0x02, 0x0f,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
93 0x02, 0x02
94 };
96 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff,
97 0xee, 0xde, 0xad, 0xbe, 0x08, 0x06, 0x00, 0x01,
98 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0xc0, 0xff,
99 0xee, 0xde, 0xad, 0xbe, 0x0a, 0x00, 0x02, 0x0f,
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00,
101 0x02, 0x02
102 };
103
108
109
113static
114void netDumpPacket(uint8_t * packet, int lg)
115{
116 int i;
117 for (i = 0; i < lg; i++) {
118 printk("%2x ", packet[i]);
119 if (i % 8 == 7) printk(" ");
120 if (i % 16 == 15) printk("\n");
121 }
122 if (i % 16 != 15) printk("\n");
123}
124
125[[maybe_unused]]
126static
127void virtioNetTraiterEmissions(VirtioReseau * vr)
128{
129 // OK, mais on les traite de quoi ?
130
131 uint8_t * buffers[2];
132 int longueurs[2];
133 VirtioFileVirtuelle * fv = &(vr->virtioPeripherique.filesVirtuelles[VR_FILE_EMISSION]);
134
135 //printk_debug(DBG_KERNEL_NET, "emission (file %x)!!!\n", fv);
136
137 // On ne veut plus être embêté
138 // virtioFileInterdireInterruption(fv);
139
140 // On va chercher une trame, a priori dans une chaîne de buffers
141 virtioFileRecupererBuffers(fv, (void*)buffers, longueurs, 2);
142
143 // On peut reprendre une activité normale
144 // virtioFileAutoriserInterruption(fv);
145}
146
151static
152void virtioNetRecevoirTrame(VirtioReseau * vr)
153{
154 uint8_t * buffers[2];
155 int longueurs[2];
156 int nbLu;
157 VirtioFileVirtuelle * fv = &(vr->virtioPeripherique.filesVirtuelles[VR_FILE_RECEPTION]);
158
159 // On ne veut plus être embêté
160 // virtioFileInterdireInterruption(fv);
161
162 // WARNING tout ce qui suit devrait être reporté à la partie basse
163
164 // On va chercher une trame, a priori dans une chaîne de buffers
165 nbLu = virtioFileRecupererBuffers(fv, (void*)buffers, longueurs, 2);
166
167#ifdef MANUX_BUFFER_RESEAU
168 BufferReseau * br;
169
170 // On fait une copie, mais ce serait mieux de la faire plus tard
171 br = bufferReseauCreer(buffers[1], longueurs[1]);
172
173 // On va maintenant le placer dans une liste qui sera traitée plus tard.
174 printk("on insere ...\n");
176#endif
177
178 printk_debug(DBG_KERNEL_NET, "%d IT recues, trame : %d/%d+%d\n",
179 vr->nbItRecues, nbLu, longueurs[0], longueurs[1]);
180
181 if (nbLu) {printk("RECU : \n");
182 netDumpPacket(buffers[1], longueurs[1]);
183 }
184
185 // On peut reprendre une activité normale
186 // virtioFileAutoriserInterruption(fv);
187}
188
192static
193void virtioNetRecevoirTramePartieBasse(void * _vr)
194{
195 VirtioReseau * vr = (VirtioReseau *)_vr;
196
197 printk("C'est triste je ne fais rien avec %d!\n", vr);
198}
199
204{
205 virtioNetRecevoirTrame(&virtioReseau);
206}
207
211static
212void virtioNetGestionInt(void * pr)
213{
214 VirtioReseau * vr = (VirtioReseau *) pr;
215 uint8_t isr;
216
217 vr->nbItRecues++;
218
219 printk_debug(DBG_KERNEL_NET, "Interruption %d !!!\n", vr->nbItRecues);
220
221 // Est-ce moi qui suis visé ?
222 inb((uint16_t)(vr->virtioPeripherique.pciEquipement->adresseES + VIRTIO_HIST_ISR), isr);
223 if (isr & 0x1) {
224 printk_debug(DBG_KERNEL_NET, "C'est pour moi, ...\n");
225 //i8259aAckIRQ(vr->virtioPeripherique.pciEquipement->interruption); fait par le handler
226
227 // La suite est à déférer dans une partie basse
228 virtioNetRecevoirTrame(vr);
229 // virtioNetTraiterEmissions(vr); // WARNING : à vérifier si ça doit être là
230 } else {
231 printk_debug(DBG_KERNEL_NET, "Balek, ...\n");
232 }
233}
234
235
240 .nom = "virtio-net",
241 .recevoirTrame = virtioNetRecevoirTramePartieBasse
242};
243
250static
251int virtioNetInitPeripherique(int PCINumeroPeripherique)
252{
253 PCIEquipement * pciEquip = PCIEquipementNumero(PCINumeroPeripherique);
254 // WARNING, va le chercher dans le virtio
255
257 uint8_t addr;
258 void * pointeur; // Pour allouer de la mémoire en
259 // réception
260
261 // On va construire un tableau de buffers (et un de leurs
262 // longueurs) pour passer à virtioFournirBuffers
263 void * buffers[2];
264 int longueurs[2];
265
266 // On renseigne la structure
268 PCINumeroPeripherique,
269 VIRTIO_NET_F_GUEST_CSUM // C'est pas moi qui check
270 | VIRTIO_NET_F_GUEST_TSO4 // Je ne fais pas de TSO
272 | VIRTIO_NET_F_GUEST_UFO // Pas d'UFO svp
273 | VIRTIO_NET_F_MRG_RXBUF // Je ne merge pas les buffers
274 | VIRTIO_NET_F_CTRL_VQ); // Pas de canal de contrôle
275
276 // On va tout de suite remplir la file de réception de
277 // buffers ([3] page 26 point 5)
278 fr = &(virtioReseau.virtioPeripherique.filesVirtuelles[0]);
279
280 // ATTENTION ici je tente de passer des trames de taille max uniquement
281 // d'où VIRTIO_TAILLE_TRAME_MAX qui remplace sizeof ...
282
283 // Pas de malloc, ...
284 pointeur = allouerPages(NB_PAGES(fr->taille*(sizeof(VirtioReseauEntete)
286
287 // Concrètement, puisque le réseau préfixe systématiquement par un
288 // entête à lui, on va lui fourni systématiquement une chaîne avec
289 // un premier buffer pour l'entête, comme ça la trame sera toute
290 // seule dans son buffer, donc directement manipulable ! Malin JP, ...
291 for (int i = 0 ; i < fr->taille/2; i++) {
292 buffers[0] = pointeur;
293 longueurs[0] = sizeof(VirtioReseauEntete);
294 pointeur += sizeof(VirtioReseauEntete);
295 buffers[1] = pointeur;
296 longueurs[1] = VIRTIO_TAILLE_TRAME_MAX;
297 pointeur += VIRTIO_TAILLE_TRAME_MAX;
299 VR_FILE_RECEPTION, // File réception
300 buffers, longueurs,
301 2,
302 VRING_DESC_F_WRITE); // pour recevoir
303 }
304
305 // Lecture de l'adresse IEEE
306 for (int i = 0; i < 6; i++){
307 inb((uint16_t)(pciEquip->adresseES + 0x14 + i), addr);
308 virtioReseau.adresseMAC[i] = addr;
309 }
310 /*
311 printk("MAC@ = ");
312 for (int i = 0 ; i < 5 ; i++) {
313 printk("%x:", virtioReseau.adresseMAC[i]);
314 }
315 printk("%x\n", virtioReseau.adresseMAC[5]);
316 */
317 // On définit notre fonction de gestion des interuptions
319 virtioNetGestionInt,
320 &virtioReseau)){
321 printk(PRINTK_CRITIQUE "Trop de handler sur l'interruption %d\n", pciEquip->interruption);
322 paniqueNoyau("Pas possible");
323 return ENOENT;
324 }
327
328 // On l'enregistre auprès du système réseau
330
331 return ESUCCES;
332}
333
337static
338void virtioNetEmettre(VirtioReseau * vr, uint8_t * trame)
339{
340 (void) vr; // WARNING, pas normal
341
342 // On va construire un tableau de buffers (et un de leurs
343 // longueurs) pour passer à virtioFournirBuffers
344 void * buffers[2];
345 int longueurs[2];
346
348
349 // On ne délègue rien à l'interface
350 virtioReseauEntete.flags = 0;
351 virtioReseauEntete.typeGSO = 0;
352 virtioReseauEntete.longueurEntete = 0;
353 virtioReseauEntete.debutSommeControle = 0;
354 virtioReseauEntete.decalageSommeControle = 0;
355
356 buffers[0] = (void *)&virtioReseauEntete;
357 longueurs[0] = sizeof(VirtioReseauEntete);
358 buffers[1] = (void*)trame;
359 longueurs[1] = 42;
360
362 1, // File émission
363 buffers, longueurs,
364 2,
365 0); // pour émettre
366
368}
369
374{
375 int PCINumeroPeripherique;
376
378
379 // On s'identifie comme pilote réseau
381
382 // On va chercher un peripherique virtio net
383 printk_debug(DBG_KERNEL_NET, "Je cherche un PCI vendeur/Id %d/%d\n",
385 PCINumeroPeripherique = PCIObtenirProchainEquipement(PCI_VENDEUR_VIRTIO,
387 printk_debug(DBG_KERNEL_NET, "Peripherique PCI %d\n", PCINumeroPeripherique);
388
389 // Initialisation de l'unique périphérique pour le moment
390 if (virtioNetInitPeripherique(PCINumeroPeripherique) == 0) {
391 printk_debug(DBG_KERNEL_NET, "Peripherique initialise !\n");
392 }
393
394 // Test d'émission
395 virtioNetEmettre(&virtioReseau, requeteARP);
396
398 return ESUCCES;
399}
400
401//Pour voir si je peux en faire 2 et avoir 2 IT
403{
405 virtioNetEmettre(&virtioReseau, requeteARP2);
407}
Définition des buffers réseau et les fonctions associcées.
int listeBufferReseauInserer(ListeBufferReseau *l, BufferReseau *b)
Insertion d'un buffer réseau à la fin d'une liste.
BufferReseau * bufferReseauCreer(void *donnees, int taille)
Création (allocation et initialisation des champs de base) d'un buffer réseau.
#define ENOENT
Definition errno.h:12
#define ESUCCES
Definition errno.h:10
typedef void(Handler(void))
void * allouerPages(uint32_t nombre)
Definition memoire.c:284
#define NB_PAGES(n)
Definition memoire.h:22
#define PRINTK_CRITIQUE
Definition printk.h:28
void printk(char *format,...)
Fonction principale d'affichage dans le noyau.
Definition printk.c:166
unsigned short uint16_t
Definition types.h:16
unsigned char uint8_t
Definition types.h:12
int i8259aAjouterHandler(int numIRQ, void(*handler)(void *), void *private)
Ajout d'un handler.
void i8259aAutoriserIRQ(uint8_t numIRQ)
Masquage d'une IRQ.
void reseauEnregistrerPilote(ReseauPilote *p)
void reseauAjouterInterface(ReseauPilote *p, void *d)
Ajout d'une nouvelle interface réseau.
#define inb(port, adresseOctet)
Lecture d'un octet depuis un port.
Definition io.h:19
#define DBG_KERNEL_NET
Definition debug.h:30
#define paniqueNoyau(fmt, args...)
Definition debug.h:107
#define printk_debug(lvl, fmt, args...)
Definition debug.h:86
int PCIObtenirProchainEquipement(uint16_t vendeur, uint16_t equipement, int precedent)
: récuperer l'identifiant du prochain équipement PCI
Definition pci.c:206
PCIEquipement * PCIEquipementNumero(int n)
Definition pci.c:226
ListeBufferReseau * listeBuffersRecus
La liste des buffers qui ont été reçus mais non encore traités.
Definition reseau.c:19
#define PCI_PERIPHERIQUE_VIRTIO_NET
Definition virtio.h:39
VirtioFileVirtuelle
Definition virtio.h:133
int virtioInitPeripheriquePCI(VirtioPeripherique *vp, int PCINum, uint32_t masque)
Definition virtio.c:173
#define VRING_DESC_F_WRITE
Definition virtio.h:76
int virtioFournirBuffers(VirtioPeripherique *vp, uint16_t id, void *bu[], int lg[], int nb, uint16_t fl)
: Fournir un(e chaine de) buffer(s) au périphérique.
Definition virtio.c:304
int virtioFileRecupererBuffers(VirtioFileVirtuelle *fv, void *bu[], int lg[], int nb)
on va récupérer des buffers
Definition virtio.c:387
#define PCI_VENDEUR_VIRTIO
Definition virtio.h:38
#define VIRTIO_HIST_ISR
Definition virtio.h:70
VirtioPeripherique
Definition virtio.h:142
VirtioPeripherique virtioPeripherique
Definition virtio-net.c:57
uint16_t nbItRecues
Definition virtio-net.c:58
uint8_t adresseMAC[6]
Definition virtio-net.c:61
: structure permettant d'identifier un équipement PCI
Definition pci.h:14
uint8_t interruption
Definition pci.h:18
uint32_t adresseES
Definition pci.h:19
Description d'un pilote d'interface réseau.
Défnition d'un buffer réseau.
#define VIRTIO_NET_F_GUEST_TSO4
Definition virtio-net.c:37
void virtioReseauPoll(void)
Definition virtio-net.c:203
struct VirtioReseau_t VirtioReseau
ReseauPilote virtioPiloteReseau
Description du pilote virtio.
Definition virtio-net.c:239
#define VIRTIO_NET_F_GUEST_CSUM
Definition virtio-net.c:34
uint8_t requeteARP[]
Definition virtio-net.c:87
#define VIRTIO_NET_F_GUEST_TSO6
Definition virtio-net.c:38
uint8_t requeteARP2[]
Definition virtio-net.c:95
#define VR_FILE_RECEPTION
Definition virtio-net.c:27
#define VIRTIO_NET_F_MRG_RXBUF
Definition virtio-net.c:46
#define VIRTIO_NET_F_CTRL_VQ
Definition virtio-net.c:48
#define VIRTIO_TAILLE_TRAME_MAX
Definition virtio-net.c:24
#define VR_FILE_EMISSION
Definition virtio-net.c:28
uint8_t unBufferALaCon[4096]
Definition virtio-net.c:107
VirtioReseauEntete
Definition virtio-net.c:75
void virtioNetTestDeuxiemeEmission(void)
Definition virtio-net.c:402
struct __attribute__((__packed__))
Description de l'entête ajouté par virtio net.
Definition virtio-net.c:67
#define VIRTIO_NET_F_GUEST_UFO
Definition virtio-net.c:40
int virtioNetInit(void)
Initialisation des périphériques.
Definition virtio-net.c:373
VirtioReseau virtioReseau
Definition virtio-net.c:80
VirtioReseauEntete virtioReseauEntete
Definition virtio-net.c:85