Ecco la situazione: sto facendo un proxy (per il momento in esecuzione sul mio laptop) che tratta le richieste HTTP (S) dai client in arrivo (per ora solo un client, cioè il mio browser Chrome sul mio laptop). Funziona senza problemi, ma è un proxy best effort, cioè non dà priorità ad alcuni tipi di traffico (streaming su SMTP, ad esempio).
Ho pensato a tre classi di priorità (minimo: 1, medio: 2 e massimo: 3) e poiché il mio traffico ha due direzioni ( LAN -> proxy -> WAN
e WAN -> proxy -> LAN
), ho pensato a sei code di priorità come queste ( la natura della coda FIFO non causa la fame dei pacchetti):
// LAN -> proxy -> WAN, from max to min priority
queue queue_to_remote_3;
queue queue_to_remote_2;
queue queue_to_remote_1;
// WAN -> proxy -> LAN, from max to min priority
queue queue_to_local_3;
queue queue_to_local_2;
queue queue_to_local_1;
Questo è lo pseudocodice (C-like) dell'algoritmo che ho fatto trattando i pacchetti in arrivo sia dalla LAN che dalla WAN: pubblicherò solo la parte che tratta LAN -> proxy -> WAN
, poiché WAN -> proxy -> LAN
ha lo stesso ragionamento, ma invece di queue_to_remote_X
utilizza queue_to_local_X
:
void algoQueues(packet pkt, int direction, int priority) {
if (direction == TO_REMOTE) {
switch (priority) {
case 1: { // MAXIMUM priority
// if queue1 is empty, just let it pass
if (queue_to_remote_1.empty()) {
letPass(pkt);
}
// if queue1 is not empty, push the arrived pkt and
// pop another pkt from the queue to let it pass
else {
queue_to_remote1.push(pkt);
packet new_pkt = queue_to_remote1.pop();
letPass(new_pkt);
}
break;
}
case 2: { // MEDIUM priority
// first check if queue1 has pkts to send
if (queue_to_remote_1.empty()) {
// if queue1 is empty, then check queue2
if (queue_to_remote_2.empty()) {
// if queue2 is empty too, just let the packet pass
letPass(pkt);
}
// if queue1 is empty and queue2 is not empty,
// push the new arrived pkt in queue2 and send
// a queued pkt from queue2
else {
queue_to_remote_2.push(pkt);
packet new_pkt = queue_to_remote_2.pop();
letPass(new_pkt);
}
}
// if queue1 is not empty, I must queue the new arrived pkt
// in queue 2 and send a queued pkt from queue1
else {
queue_to_remote_2.push(pkt);
packet new_pkt = queue_to_remote_1.pop();
letPass(new_pkt);
}
break;
}
case 3: { // MINIMUM priority
// first check if queue1 has pkts to send
if (queue_to_remote_1.empty()) {
// if queue1 is empty, then check queue2
if (queue_to_remote_2.empty()) {
// if queue3 is empty, just let it pass
if (queue_to_remote_3.empty()) {
letPass(pkt);
}
// if queue3 is not empty, push the arrived pkt
// in queue3 and pop another pkt from the
// same queue to let it pass
else {
queue_to_remote_3.push(pkt);
packet new_pkt = queue_to_remote_3.pop();
letPass(new_pkt);
}
}
// if queue2 is not empty and queue1 is empty, push the
// arrived pkt in queue3, get a pkt from queue2 and send it
else {
queue_to_remote_3.push(pkt);
packet new_pkt = queue_to_remote_2.pop();
letPass(new_pkt);
}
}
// if queue1 is not empty, queue the pkt in queue3
// and send a pkt from queue1
else {
queue_to_remote_3.push(pkt);
packet new_pkt = queue_to_remote_1.pop();
letPass(new_pkt);
}
break;
}
default: {
printf("To remote: unknown priority, strange...\n");
exit(EXIT_FAILURE);
}
}
}
else if (direction == TO_LOCAL) {
/* ... */
}
}
Un osservatore intelligente potrebbe obiettare: "quando inserisci il primo pacchetto ???", e questo è il mio problema; la prima volta che viene chiamato questo algoritmo, tutte le code sono vuote, quindi ogni pacchetto passerà!
Non posso spingere il primo pacchetto di nessuna priorità nella sua coda e interrompere l'istruzione switch
per sbloccare tutti gli altri if
s, sembra stupido: il mio ragionamento (e quindi il mio algoritmo) è sbagliato, o sto usando la struttura dati sbagliata?