Dezvoltatorii de la Cloudflare au realizat lucrări de optimizare a performanței criptării pe disc în nucleul Linux. Ca urmare, au fost pregătite pentru subsystema și Crypto API, care au permis în testele sintetice creșterea cu peste două ori a capacității de transmisie la citire și scriere, precum și reducerea la jumătate a întârzierilor. În testele pe echipamente reale, cheltuielile din criptare au fost reduse practic la nivelul observat la utilizarea unui disc fără criptare.
Cloudflare folosește dm-crypt pentru criptarea datelor pe dispozitivele utilizate pentru cache-ul de conținut în rețeaua CDN. Dm-crypt funcționează la nivelul dispozitivului de bloc și efectuează criptarea cererilor de intrare/ieșire pentru scriere și decriptarea cererilor de citire, acționând ca un strat între dispozitivul de bloc și driverul sistemului de fișiere.
Pentru evaluarea performanței dm-crypt, s-a folosit pachetul unde s-au măsurat vitezele de acces la partiții criptate și nesecurizate pe un disc RAM amplasat în RAM pentru a exclude fluctuațiile de performanță ale discurilor și a se concentra pe performanța codului. Pentru partițiile nesecurizate, performanța la citire și scriere s-a menținut la aproximativ 1126 MB/s, însă activarea criptării a redus viteza de 7 ori ajungând la 147 MB/s.
La început, au existat suspiciuni privind utilizarea algoritmilor ineficienți în criptosistemul nucleului. Dar în teste s-a folosit cel mai rapid algoritm aes-xts cu o cheie de criptare de 256, iar performanța sa în cadrul „cryptsetup benchmark” este de peste două ori mai mare decât rezultatul obținut în testul cu discul RAM. Experimentele cu flag-urile dm-crypt pentru optimizarea performanței nu au avut rezultate: utilizând flag-ul „—perf-same_cpu_crypt”, performanța a scăzut la 136 MB/s, iar cu flag-ul „—perf-submit_from_crypt_cpus” a crescut doar la 166 MB/s.
O analiză mai profundă a logicii de funcționare a arătat că dm-crypt nu este atât de simplu cum pare — la primirea unei cereri de scriere de la driverul FS, dm-crypt nu o procesează imediat, ci o plasează în coada „kcryptd”, care nu este gestionată imediat, ci la un moment convenabil. Din coadă, cererea este trimisă către Linux Crypto API pentru a efectua criptarea. Însă, deoarece Crypto API folosește un model de execuție asincron, criptarea nu se efectuează imediat, ci trece prin încă o coadă. După finalizarea criptării, dm-crypt poate încerca să execute sortarea cererilor de scriere în așteptare, utilizând un arbore de căutare. . La final, un thread separat al nucleului preia din nou, cu o întârziere specifică, cererile acumulate de intrare/ieșire și le trimite în stiva dispozitivului bloc.
La citire, mai întâi dm-crypt adaugă în coada „kcryptd_io” o cerere pentru a obține date de pe dispozitiv. După un timp, datele devin disponibile și sunt plasați în coada „kcryptd” pentru decriptare.
Kcryptd trimite cererea către Linux Crypto API, care decriptează informația în mod asincron. Cererile nu trec întotdeauna prin toate cozile, dar în cel mai rău scenariu, cererea de scriere rămâne în cozi de până la 4 ori, iar cererea de citire de până la 3 ori. Fiecare intrare în coadă duce la apariția întârzierilor, care sunt principala cauză a scăderii semnificative a performanței dm-crypt.
Utilizarea cozilor este determinată de necesitatea de a lucra în condiții de întrerupere. În 2005, când a fost implementat modelul actual de funcționare dm-crypt bazat pe cozi, Crypto API nu era încă asincron. După trecerea Crypto API la un model de execuție asincron a început să se aplice, de fapt, o dublă protecție. Cozile au fost introduse și pentru a economisi consumul stivei nucleului, dar după creșterea acesteia în 2014, aceste optimizări au devenit irelevante. O coadă suplimentară „kcryptd_io” a fost introdusă pentru a depăși un bottleneck care ducea la așteptarea alocării de memorie în cazul unui număr mare de cereri. În 2015 a fost introdusă suplimentar o fază de sortare, deoarece cererile de criptare pe sisteme multiprocesor puteau să se finalizeze fără respectarea ordinii de trimitere (în loc de un acces secvențial la disc, se făcea acces aleatoriu, iar planificatorul CFQ nu funcționa eficient). În prezent, utilizarea unităților SSD a făcut ca sortarea să își piardă sensul, iar planificatorul CFQ deja nu este folosit în nucleu.
Având în vedere că unitățile moderne au devenit mai rapide și mai inteligente, sistemul de distribuție a resurselor în nucleul Linux a fost reevaluat și unele subsisteme au fost reproiectate, inginerii Cloudflare în dm-crypt a fost introdus un nou mod de funcționare, scutit de utilizarea cozii inutile și a apelurilor asincrone. Modificarea se activează printr-un steag separat „force_inline” și transformă dm-crypt într-o formă simplă de proxy, care criptează și decriptează cererile primite. Interacțiunea cu Crypto API a fost optimizată prin alegerea explicită a algoritmilor de criptare care funcționează în mod sincron și nu folosesc cozi de cereri. Pentru operarea în mod sincron cu Crypto API a fost un modul, care permite utilizarea FPU/AES-NI pentru accelerare și care transferă direct cererile de criptare și decriptare.
În cele din urmă, s-a reușit, la testarea unui disc RAM, să se crească performanța dm-crypt de mai mult de două ori — performanța a crescut de la 294 MB/s (2 x 147 MB/s) la 640 MB/s, ceea ce se apropie foarte mult de performanța criptării brute (696 MB/s).
În testarea încărcărilor pe servere reale, noua implementare a arătat o performanță foarte apropiată de configurația care funcționează fără criptare, iar activarea criptării pe serverele cu cache Cloudflare nu a influențat viteza de răspuns. În continuare, Cloudflare plănuiește să includă patch-urile pregătite în nucleul principal al Linux, dar înainte de aceasta, va fi necesară o reproiectare, deoarece acestea sunt optimizate pentru o anumită încărcare și nu acoperă toate domeniile de aplicare, de exemplu, criptarea pe dispozitive încorporate cu putere redusă.
Sursa: opennet.ro
