Zum Inhalt springen

Network Block Device

aus Wikipedia, der freien EnzyklopÀdie

Ein Network Block Device (engl. fĂŒr Netzwerk-BlockgerĂ€t, abgekĂŒrzt NBD) ist eine Art virtuelle Festplatte, auf die ein Rechner via Internetprotokoll zugreifen kann. Das NBD wird von einem NBD-Server bereitgestellt. Er bietet hierfĂŒr eine eigene Festplatte, Festplattenpartition oder eine Datei als NBD bestimmten anderen Rechnern (Clients) an. Ein anderer Rechner (oder auch der gleiche) kann sich ĂŒber eine TCP-Verbindung mit dem NBD-Server verbinden und anschließend das NBD wie eine eigene lokale Festplatte benutzen.

Derzeit existiert nur fĂŒr Linux eine vollstĂ€ndige NBD-Implementierung. Linux spricht sĂ€mtliche Massenspeicher als sogenannte BlockgerĂ€te an. Wenn ein Linux-Rechner ein Network Block Device nutzen soll, muss NBD support in der Linux-Kernel-Konfiguration aktiviert sein, bzw. das Kernel-Modul nbd.ko geladen sein. Ein Userspace-Hilfsprogramm namens nbd-client stellt nun die TCP-Verbindung zum NBD-Server her, gibt die bestehende Verbindung an den Kernel weiter und beendet sich dann. Dies hat den Vorteil, dass der Kernel sich nicht mit dem Verbindungsaufbau (und einer eventuellen Authentisierung usw.) befassen muss.

Der NBD-Server ist betriebssystemunabhÀngig. Er kann also auch auf einem Nicht-Linux-System laufen, da keine Linux-spezifischen Funktionen benötigt werden. Es existiert ein Programm namens nbd-server, das nichts weiter tut, als eine gegebene Datei (oder Partition etc.) an einem angegebenen TCP-Port bereitzustellen.

Prinzipiell ist es möglich, ĂŒber NBD einen festplattenlosen Rechner zu betreiben, der als einzigen Massenspeicher ein NBD besitzt. Da jedoch zum Aufbau der Verbindung noch ein externes Programm (nbd-client) benötigt wird, ist dies nur mit Konzepten wie der init-ramdisk zu realisieren, einem virtuellen Dateisystem, welches im RAM gehalten wird und im Kernel selbst gespeichert ist, sodass es nach dem Booten zur VerfĂŒgung steht.

Da die Originalversion von NBD einige SchwĂ€chen hat (z. B. die Begrenzung auf 4 Gigabyte pro NBD), gibt es verschiedene Erweiterungen, die teilweise als „enhanced NBD“ bezeichnet werden. Diese sind jedoch inkompatibel zum Original-NBD.

NBD-Protokoll (ab Version 2.6)

[Bearbeiten | Quelltext bearbeiten]

Das Protokoll ist ein BinÀrprotokoll. SÀmtliche Mehrbytewerte werden dabei in Network Byte Order gesendet.

Zuerst kommt eine Initialisierungsphase, bei der Daten zwischen dem NBD-Server und dem NBD-Clientprogramm ausgetauscht werden. Dieses Protokoll ist unabhÀngig vom NBD-Treiber im Linux-Kernel und variiert bei verschiedenen NBD-Implementierungen.

Version ≀2.9.16

[Bearbeiten | Quelltext bearbeiten]

Das alte Handshake-Protokoll unterstĂŒtzt genau ein Block Device pro Port. Sobald ein Client sich zum NBD-Server verbunden hat, sendet der Server folgende Datenstruktur:

NBD Initialization packet (Server→Client)[1]
OffsetDatentypNameBeschreibung
0char[8]INIT_PASSWDIdentifizierungsstring {'N', 'B', 'D', 'M', 'A', 'G', 'I', 'C'}
8uint64_tcliserv_magicMagic Number 0x00420281861253
16uint64_texport_sizeGrĂ¶ĂŸe des exportierten Blockdevices (in Byte)
24uint32_tflagsFlags:
  • Bit 0: Es sind Flags vorhanden
  • Bit 1: GerĂ€t ist read-only
  • Bit 2: GerĂ€t unterstĂŒtzt „FLUSH“-Befehl zum Leeren von Schreibcaches
  • Bit 3 und 4: ungenutzt
  • Bit 5: GerĂ€t unterstĂŒtzt den TRIM-Befehl, mit dem das Dateisystem dem Blocklayer freigewordene mitteilen kann
28char[124]reservedReserviert (Derzeit gefĂŒllt mit Nullbytes)

Akzeptiert der Client den Identifizierungsstring oder die Magic Number nicht, schließt er die Verbindung. Andernfalls gilt die Verbindung als erfolgreich aufgebaut.

Version ≄ 2.9.17

[Bearbeiten | Quelltext bearbeiten]

Das neue Handshake-Protokoll benutzt den IANA-registrierten Port 10809 und ein anderes Nachrichtenformat, das dem Server erlaubt, ĂŒber einen TCP-Port mehrere BlockgerĂ€te anzubieten, aus denen der Client ĂŒber ihren Namen eines auswĂ€hlen kann. ZusĂ€tzlich wurden die 32 Bit flags in 2 16-Bit-Teile aufgespalten, die es erlauben, serverglobale und gerĂ€teabhĂ€ngige Flags zu trennen.

Server Init packet (Server→Client)[2]
OffsetDatentypNameBeschreibung
0char[8]INIT_PASSWDIdentifizierungsstring {'N', 'B', 'D', 'M', 'A', 'G', 'I', 'C'}
8uint64_tcliserv_magicMagic Number 0x49484156454F5054 (=„IHAVEOPT“)
16uint16_tserver_flagsFlags, die fĂŒr den gesamten Server gelten. Üblicherweise haben die Flags den Wert 0003hex. Die Bits bedeuten im Einzelnen:
Bit 0
NBD_FLAG_FIXED_NEW_STILE: Gesetztes Bit zeigt an, dass ein bestimmter Handshake-Bug im Server gefixt ist
Bit 1
NBD_FLAG_NO_ZEROES: Gesetztes Bit zeigt an, dass die Headernachricht nicht mit 124 Nullbytes aufgefĂŒllt wird

Der Client antwortet mit seinen Flags. Da bisher keine Flags definiert sind, bestehen sie nur aus 32 Nullbits:

Client Init packet (Server→Client)
OffsetDatentypNameBeschreibung
0uint32_tclient_flagsbisher gleiche Bedeutung wie server_flags, also ebenfalls ĂŒblicherweise 0000'0003hex.

Anschließend sendet der Client verschiedene Optionen, die der Server entsprechend akzeptierend oder ablehnend quittiert:

Option packet (Client→Server)
OffsetDatentypNameBeschreibung
0uint64_tcliserv_magicMagic Number 0x49484156454F5054 (=„IHAVEOPT“)
8uint32_toption_numberKennnummer/Typ der Option
12uint32_toption_lengthLĂ€nge der Option (in Bytes)
16variabeloption_dataDaten der Option (abhÀngig vom Optionstyp)

Bisher sind 3 Optionen definiert:

NBD Optionen
NameWertBedeutung
NBD_OPT_EXPORT_NAME1Client wÀhlt Namen des BlockgerÀtes: der Name folgt im option_data-Feld. Diese Option beendet automatisch die Optionsliste. Der Server schickt den gerÀteabhÀngigen Teil der Initialisierung (siehe unten).
NBD_OPT_ABORT2Client möchte die Verbindung beenden
NBD_OPT_LIST3Client möchte eine Liste mit den Namen der exportierten BlockgerÀte

Der Server antwortet auf ein Option Paket mit einem Reply-Paket:

Reply packet (Server→Client)
OffsetDatentypNameBeschreibung
0uint64_treply_magicMagic Number 0x0003e889045565a9
8uint32_toption_numberKennnummer/Typ der Option, die beantwortet wird[3]
12uint32_treply_typeTyp der Antwort
16uint32_treply_lengthLĂ€nge der Antwortdaten
20variabelreply_dataAntwortdaten, sofern reply_length > 0

Folgende Antworttypen sind bisher definiert:

Reply types
NameWertBedeutung
NBD_REP_ACK1Der Server akzeptiert die Option oder hat keine weiteren Antwortdaten (bei NBD_OPT_LIST)
NBD_REP_SERVER2Beschreibung des BlockgerĂ€tes. Es folgt die LĂ€nge des Namens als 32-Bit-Nummer, der Name, und – falls noch Platz im Antwortpaket ist – evtl. weitere beschreibende Details als Klartext.
NBD_REP_ERR_UNSUP8000 0001hexClient hat eine unbekannte Option geschickt
NBD_REP_ERR_POLICY8000 0002hexDer Server hat die Option verstanden, aber dem Server ist nicht erlaubt, die Option anzunehmen (z. B. NBD_OPT_LIST kann in der Konfigurationsdatei erlaubt oder verboten werden)
NBD_REP_ERR_INVALID8000 0003hexDer Server hat die Option verstanden, doch sie war syntaktisch ungĂŒltig
NBD_REP_ERR_PLATFORM8000 0004hexDie Option wird von der Plattform, auf der der Server lĂ€uft, nicht unterstĂŒtzt. (derzeit ungenutzt)
Hexdump des Datenverkehrs in der Initialisierungsphase zwischen NBD-Client und -Server. Der Client fragt die Liste der angebotenen GerĂ€te ab und der Server listet zwei GerĂ€te (mit Namen „alfa“ und „bravo“) auf.

Die Aushandelsphase ist abgeschlossen, sobald der Server die NBD_OPT_EXPORT_NAME-Option positiv quittiert hat. Er schickt daraufhin die Kenndaten des exportierten BlockgerÀtes an den Client:

Device Init packet (Server→Client)
OffsetDatentypNameBeschreibung
0uint64_tdevice_sizeGrĂ¶ĂŸe des exportierten BlockgerĂ€tes (in Byte)
8uint16_tdevice_flagsFlags, die fĂŒr das exportierte GerĂ€t gelten:
  • Bit 0: Es existieren Flags
  • Bit 1: GerĂ€t ist read-only
  • Bit 2: Server & GerĂ€t unterstĂŒtzen das NBD_CMD_FLUSH-Kommando
  • Bit 3: Server & GerĂ€t unterstĂŒtzen das NBD_CMD_FLAG_FUA-Flag
  • Bit 4: NBD_FLAG_ROTATIONAL: exportierte Daten liegen auf einem rotierenden Medium (klassische Festplatte), was der Client bei dem Zugriffsmuster auf die Blöcke berĂŒcksichtigen kann
  • Bit 5: Server & GerĂ€t unterstĂŒtzen das NBD_FLAG_SEND_TRIM-Kommand
10uint8_t[124]paddingungenutzt, alle 0

Der NBD-Client leitet die Informationen ĂŒber die GrĂ¶ĂŸe des Blockdevices, eventuelle Flags und den geöffneten Socket ĂŒber spezielle Systemaufrufe an den Kernel weiter und beendet sich. Der Kernel ĂŒbernimmt dann die weitere Kommunikation ĂŒber diesen Socket.

Der Kernel auf Clientseite stellt nun Lese- und Schreibanfragen (Requests) an den Server. Diese haben folgenden Paketaufbau:

NBD Request (Client→Server)[4]
OffsetDatentypNameBeschreibung
0uint32_tmagicMagic Number 0x25609513
4uint32_ttype0: Lesezugriff; 1: Schreibzugriff; 2: kontrolliertes Verbindungsende; 3: Flush cache; 4: TRIM-Kommando
8char[8]handle8 Bytes, die im Reply identisch mitgeschickt werden, um dieses einem Request zuordnen zu können
16uint64_tfromOffset (in Bytes), ab dem gelesen/geschrieben werden soll
24uint32_tlenLĂ€nge des Datenblocks

Bei Schreibzugriffen folgen unmittelbar darauf die zu schreibenden Daten. Der Server beantwortet jeden Request mit einer Antwort (Reply). Diese hat folgenden Aufbau:

NBD Reply (Server→Client)[4]
OffsetDatentypNameBeschreibung
0uint32_tmagicMagic Number 0x67446698
4uint32_terror0=OK (kein Fehler aufgetreten)
8char[8]handleKopie des Handles im zugehörigen Request

Bei Antworten auf Lese-Requests folgen unmittelbar darauf die angeforderten Daten.

  • Loop device: Die gleiche Idee mit einem lokalen GerĂ€t
  • iSCSI: Ein konkurrierendes System
  • Network File System: Agiert auf einer anderen Ebene, hat dafĂŒr aber auch einen weitaus grĂ¶ĂŸeren Bekanntheitsgrad

Einzelnachweise

[Bearbeiten | Quelltext bearbeiten]
  1. ↑ Aus dem Quellcode von nbd-2.9.13/cliserv.h
  2. ↑ Aus dem Quellcode von nbd-3.2/proto.txt
  3. ↑ Wird entgegen der Protokoll-Beschreibung in Host-Byteorder gesendet. Wert vom Client beim Einlesen ignoriert.
  4. 1 2 Aus dem Header /usr/include/linux/nbd.h