Network Block Device
EinNetwork Block Device(engl.fürNetzwerk-Blockgerät,abgekürztNBD) ist eine ArtvirtuelleFestplatte,auf die einRechnerviaInternetprotokollzugreifen kann. Das NBD wird von einem NBD-Serverbereitgestellt. Er bietet hierfür eine eigene Festplatte,Festplattenpartitionoder eineDateials NBD bestimmten anderen Rechnern (Clients) an. Ein anderer Rechner (oder auch der gleiche) kann sich über eineTCP-Verbindung mit dem NBD-Server verbinden und anschließend das NBD wie eine eigene lokale Festplatte benutzen.
Derzeit existiert nur fürLinuxeinevollständigeNBD-Implementierung. Linux spricht sämtlicheMassenspeicherals sogenannteBlockgerätean. Wenn ein Linux-Rechner ein Network Block Device nutzen soll, mussNBD supportin derLinux-Kernel-Konfiguration aktiviert sein, bzw. dasKernel-Modulnbd.kogeladen sein. EinUserspace-Hilfsprogrammnamensnbd-clientstellt nun die TCP-Verbindung zum NBD-Server her, gibt die bestehende Verbindung an denKernelweiter und beendet sich dann. Dies hat den Vorteil, dass der Kernel sich nicht mit dem Verbindungsaufbau (und einer eventuellenAuthentisierungusw.) 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 namensnbd-server,das nichts weiter tut, als eine gegebene Datei (oder Partition etc.) an einem angegebenen TCP-Portbereitzustellen.
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 derinit-ramdiskzu realisieren, einemvirtuellen Dateisystem,welches imRAMgehalten 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 4Gigabytepro NBD), gibt es verschiedene Erweiterungen, die teilweise als „enhanced NBD “bezeichnet werden. Diese sind jedochinkompatibelzum Original-NBD.
NBD-Protokoll (ab Version 2.6)
BearbeitenDas Protokoll ist ein Binärprotokoll. Sämtliche Mehrbytewerte werden dabei inNetwork Byte Ordergesendet.
Handshake
BearbeitenZuerst kommt eine Initialisierungsphase, bei der Daten zwischen dem NBD-Server und dem NBD-Clientprogramm ausgetauscht werden. Dieses Protokoll istunabhängigvom NBD-Treiber im Linux-Kernel und variiert bei verschiedenen NBD-Implementierungen.
Version ≤2.9.16
BearbeitenDas alte Handshake-Protokoll unterstützt genau ein Block Device pro Port. Sobald ein Client sich zum NBD-Server verbunden hat, sendet der Server folgendeDatenstruktur:
Offset | Datentyp | Name | Beschreibung |
---|---|---|---|
0 | char[8] | INIT_PASSWD | Identifizierungsstring{'N', 'B', 'D', 'M', 'A', 'G', 'I', 'C'}
|
8 | uint64_t | cliserv_magic | Magic Number0x00420281861253 |
16 | uint64_t | export_size | Größe des exportierten Blockdevices (in Byte) |
24 | uint32_t | flags | Flags:
|
28 | char[124] | reserved | Reserviert (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
BearbeitenDas 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 Bitflagsin 2 16-Bit-Teile aufgespalten, die es erlauben, serverglobale und geräteabhängige Flags zu trennen.
Offset | Datentyp | Name | Beschreibung |
---|---|---|---|
0 | char[8] | INIT_PASSWD | Identifizierungsstring{'N', 'B', 'D', 'M', 'A', 'G', 'I', 'C'}
|
8 | uint64_t | cliserv_magic | Magic Number0x49484156454F5054 (=„IHAVEOPT “) |
16 | uint16_t | server_flags | Flags, die für den gesamten Server gelten. Üblicherweise haben die Flags den Wert 0003hex.Die Bits bedeuten im Einzelnen:
|
Der Client antwortet mit seinen Flags. Da bisher keine Flags definiert sind, bestehen sie nur aus 32 Nullbits:
Offset | Datentyp | Name | Beschreibung |
---|---|---|---|
0 | uint32_t | client_flags | bisher 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:
Offset | Datentyp | Name | Beschreibung |
---|---|---|---|
0 | uint64_t | cliserv_magic | Magic Number0x49484156454F5054 (=„IHAVEOPT “) |
8 | uint32_t | option_number | Kennnummer/Typ der Option |
12 | uint32_t | option_length | Länge der Option (in Bytes) |
16 | variabel | option_data | Daten der Option (abhängig vom Optionstyp) |
Bisher sind 3 Optionen definiert:
Name | Wert | Bedeutung |
---|---|---|
NBD_OPT_EXPORT_NAME | 1 | Client wählt Namen des Blockgerätes: der Name folgt imoption_data -Feld. Diese Option beendet automatisch die Optionsliste. Der Server schickt den geräteabhängigen Teil der Initialisierung (siehe unten).
|
NBD_OPT_ABORT | 2 | Client möchte die Verbindung beenden |
NBD_OPT_LIST | 3 | Client möchte eine Liste mit den Namen der exportierten Blockgeräte |
Der Server antwortet auf ein Option Paket mit einem Reply-Paket:
Offset | Datentyp | Name | Beschreibung |
---|---|---|---|
0 | uint64_t | reply_magic | Magic Number0x0003e889045565a9 |
8 | uint32_t | option_number | Kennnummer/Typ der Option, die beantwortet wird[3] |
12 | uint32_t | reply_type | Typ der Antwort |
16 | uint32_t | reply_length | Länge der Antwortdaten |
20 | variabel | reply_data | Antwortdaten, sofern reply_length > 0 |
Folgende Antworttypen sind bisher definiert:
Name | Wert | Bedeutung |
---|---|---|
NBD_REP_ACK | 1 | Der Server akzeptiert die Option oder hat keine weiteren Antwortdaten (bei NBD_OPT_LIST) |
NBD_REP_SERVER | 2 | Beschreibung 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_UNSUP | 8000 0001hex | Client hat eine unbekannte Option geschickt |
NBD_REP_ERR_POLICY | 8000 0002hex | Der 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_INVALID | 8000 0003hex | Der Server hat die Option verstanden, doch sie war syntaktisch ungültig |
NBD_REP_ERR_PLATFORM | 8000 0004hex | Die Option wird von der Plattform, auf der der Server läuft, nicht unterstützt. (derzeit ungenutzt) |
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:
Offset | Datentyp | Name | Beschreibung |
---|---|---|---|
0 | uint64_t | device_size | Größe des exportierten Blockgerätes (in Byte) |
8 | uint16_t | device_flags | Flags, die für das exportierte Gerät gelten:
|
10 | uint8_t[124] | padding | ungenutzt, alle 0 |
Datenphase
BearbeitenDer NBD-Client leitet die Informationen über die Größe des Blockdevices, eventuelle Flags und den geöffnetenSocketüber spezielleSystemaufrufean 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:
Offset | Datentyp | Name | Beschreibung |
---|---|---|---|
0 | uint32_t | magic | Magic Number0x25609513 |
4 | uint32_t | type | 0: Lesezugriff; 1: Schreibzugriff; 2: kontrolliertes Verbindungsende; 3: Flush cache; 4:TRIM-Kommando |
8 | char[8] | handle | 8 Bytes, die im Reply identisch mitgeschickt werden, um dieses einem Request zuordnen zu können |
16 | uint64_t | from | Offset (in Bytes), ab dem gelesen/geschrieben werden soll |
24 | uint32_t | len | Lä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:
Offset | Datentyp | Name | Beschreibung |
---|---|---|---|
0 | uint32_t | magic | Magic Number 0x67446698 |
4 | uint32_t | error | 0=OK (kein Fehler aufgetreten) |
8 | char[8] | handle | Kopie des Handles im zugehörigen Request |
Bei Antworten auf Lese-Requests folgen unmittelbar darauf die angeforderten Daten.
Siehe auch
Bearbeiten- 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