xref: /openbmc/qemu/include/block/nbd.h (revision 0f397dcfecc9211d12c2c720c01eb32f0eaa7d23)
1737e150eSPaolo Bonzini /*
28d2931dcSEric Blake  *  Copyright Red Hat
3737e150eSPaolo Bonzini  *  Copyright (C) 2005  Anthony Liguori <anthony@codemonkey.ws>
4737e150eSPaolo Bonzini  *
5737e150eSPaolo Bonzini  *  Network Block Device
6737e150eSPaolo Bonzini  *
7737e150eSPaolo Bonzini  *  This program is free software; you can redistribute it and/or modify
8737e150eSPaolo Bonzini  *  it under the terms of the GNU General Public License as published by
9737e150eSPaolo Bonzini  *  the Free Software Foundation; under version 2 of the License.
10737e150eSPaolo Bonzini  *
11737e150eSPaolo Bonzini  *  This program is distributed in the hope that it will be useful,
12737e150eSPaolo Bonzini  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13737e150eSPaolo Bonzini  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14737e150eSPaolo Bonzini  *  GNU General Public License for more details.
15737e150eSPaolo Bonzini  *
16737e150eSPaolo Bonzini  *  You should have received a copy of the GNU General Public License
17737e150eSPaolo Bonzini  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18737e150eSPaolo Bonzini  */
19737e150eSPaolo Bonzini 
20737e150eSPaolo Bonzini #ifndef NBD_H
21737e150eSPaolo Bonzini #define NBD_H
22737e150eSPaolo Bonzini 
2356ee8626SKevin Wolf #include "block/export.h"
241c778ef7SDaniel P. Berrange #include "io/channel-socket.h"
25f95910feSDaniel P. Berrange #include "crypto/tlscreds.h"
26e6798f06SVladimir Sementsov-Ogievskiy #include "qapi/error.h"
27fcb9e051SPhilippe Mathieu-Daudé #include "qemu/bswap.h"
28737e150eSPaolo Bonzini 
298d2931dcSEric Blake typedef struct NBDExport NBDExport;
308d2931dcSEric Blake typedef struct NBDClient NBDClient;
318d2931dcSEric Blake typedef struct NBDClientConnection NBDClientConnection;
32fd358d83SEric Blake typedef struct NBDMetaContexts NBDMetaContexts;
338d2931dcSEric Blake 
3456ee8626SKevin Wolf extern const BlockExportDriver blk_exp_nbd;
3556ee8626SKevin Wolf 
36fb1c2aaaSEric Blake /*
37fb1c2aaaSEric Blake  * NBD_DEFAULT_HANDSHAKE_MAX_SECS: Number of seconds in which client must
38fb1c2aaaSEric Blake  * succeed at NBD_OPT_GO before being forcefully dropped as too slow.
39fb1c2aaaSEric Blake  */
40fb1c2aaaSEric Blake #define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10
41fb1c2aaaSEric Blake 
42*c8a76dbdSEric Blake /*
43*c8a76dbdSEric Blake  * NBD_DEFAULT_MAX_CONNECTIONS: Number of client sockets to allow at
44*c8a76dbdSEric Blake  * once; must be large enough to allow a MULTI_CONN-aware client like
45*c8a76dbdSEric Blake  * nbdcopy to create its typical number of 8-16 sockets.
46*c8a76dbdSEric Blake  */
47*c8a76dbdSEric Blake #define NBD_DEFAULT_MAX_CONNECTIONS 100
48*c8a76dbdSEric Blake 
49c8a3a1b6SEric Blake /* Handshake phase structs - this struct is passed on the wire */
50c8a3a1b6SEric Blake 
518d2931dcSEric Blake typedef struct NBDOption {
52c8a3a1b6SEric Blake     uint64_t magic; /* NBD_OPTS_MAGIC */
53c8a3a1b6SEric Blake     uint32_t option; /* NBD_OPT_* */
54c8a3a1b6SEric Blake     uint32_t length;
558d2931dcSEric Blake } QEMU_PACKED NBDOption;
56c8a3a1b6SEric Blake 
578d2931dcSEric Blake typedef struct NBDOptionReply {
58c8a3a1b6SEric Blake     uint64_t magic; /* NBD_REP_MAGIC */
59c8a3a1b6SEric Blake     uint32_t option; /* NBD_OPT_* */
60c8a3a1b6SEric Blake     uint32_t type; /* NBD_REP_* */
61c8a3a1b6SEric Blake     uint32_t length;
628d2931dcSEric Blake } QEMU_PACKED NBDOptionReply;
63c8a3a1b6SEric Blake 
6425c14678SVladimir Sementsov-Ogievskiy typedef struct NBDOptionReplyMetaContext {
6525c14678SVladimir Sementsov-Ogievskiy     NBDOptionReply h; /* h.type = NBD_REP_META_CONTEXT, h.length > 4 */
6625c14678SVladimir Sementsov-Ogievskiy     uint32_t context_id;
6771719cd5SEric Blake     /* metadata context name follows */
6825c14678SVladimir Sementsov-Ogievskiy } QEMU_PACKED NBDOptionReplyMetaContext;
6925c14678SVladimir Sementsov-Ogievskiy 
70bfe04d0aSEric Blake /* Track results of negotiation */
71bfe04d0aSEric Blake typedef enum NBDMode {
72bfe04d0aSEric Blake     /* Keep this list in a continuum of increasing features. */
73bfe04d0aSEric Blake     NBD_MODE_OLDSTYLE,     /* server lacks newstyle negotiation */
74bfe04d0aSEric Blake     NBD_MODE_EXPORT_NAME,  /* newstyle but only OPT_EXPORT_NAME safe */
75bfe04d0aSEric Blake     NBD_MODE_SIMPLE,       /* newstyle but only simple replies */
76bfe04d0aSEric Blake     NBD_MODE_STRUCTURED,   /* newstyle, structured replies enabled */
77d95ffb6fSEric Blake     NBD_MODE_EXTENDED,     /* newstyle, extended headers enabled */
78bfe04d0aSEric Blake } NBDMode;
79bfe04d0aSEric Blake 
80297365b4SEric Blake /* Transmission phase structs */
81297365b4SEric Blake 
82297365b4SEric Blake /*
83297365b4SEric Blake  * Note: NBDRequest is _NOT_ the same as the network representation of an NBD
84297365b4SEric Blake  * request!
8556af2ddaSPaolo Bonzini  */
868d2931dcSEric Blake typedef struct NBDRequest {
8722efd811SEric Blake     uint64_t cookie;
88b2578459SEric Blake     uint64_t from;  /* Offset touched by the command */
89b2578459SEric Blake     uint64_t len;   /* Effect length; 32 bit limit without extended headers */
90c8a3a1b6SEric Blake     uint16_t flags; /* NBD_CMD_FLAG_* */
91c8a3a1b6SEric Blake     uint16_t type;  /* NBD_CMD_* */
92297365b4SEric Blake     NBDMode mode;   /* Determines which network representation to use */
931dec4643SEric Blake     NBDMetaContexts *contexts; /* Used by NBD_CMD_BLOCK_STATUS */
948d2931dcSEric Blake } NBDRequest;
95737e150eSPaolo Bonzini 
96caad5384SVladimir Sementsov-Ogievskiy typedef struct NBDSimpleReply {
97caad5384SVladimir Sementsov-Ogievskiy     uint32_t magic;  /* NBD_SIMPLE_REPLY_MAGIC */
98caad5384SVladimir Sementsov-Ogievskiy     uint32_t error;
9922efd811SEric Blake     uint64_t cookie;
100caad5384SVladimir Sementsov-Ogievskiy } QEMU_PACKED NBDSimpleReply;
101caad5384SVladimir Sementsov-Ogievskiy 
102bae245d1SEric Blake /* Header of all structured replies */
103bae245d1SEric Blake typedef struct NBDStructuredReplyChunk {
104bae245d1SEric Blake     uint32_t magic;  /* NBD_STRUCTURED_REPLY_MAGIC */
105bae245d1SEric Blake     uint16_t flags;  /* combination of NBD_REPLY_FLAG_* */
106bae245d1SEric Blake     uint16_t type;   /* NBD_REPLY_TYPE_* */
10722efd811SEric Blake     uint64_t cookie; /* request handle */
108bae245d1SEric Blake     uint32_t length; /* length of payload */
109bae245d1SEric Blake } QEMU_PACKED NBDStructuredReplyChunk;
110bae245d1SEric Blake 
111d95ffb6fSEric Blake typedef struct NBDExtendedReplyChunk {
112d95ffb6fSEric Blake     uint32_t magic;  /* NBD_EXTENDED_REPLY_MAGIC */
113d95ffb6fSEric Blake     uint16_t flags;  /* combination of NBD_REPLY_FLAG_* */
114d95ffb6fSEric Blake     uint16_t type;   /* NBD_REPLY_TYPE_* */
115d95ffb6fSEric Blake     uint64_t cookie; /* request handle */
116d95ffb6fSEric Blake     uint64_t offset; /* request offset */
117d95ffb6fSEric Blake     uint64_t length; /* length of payload */
118d95ffb6fSEric Blake } QEMU_PACKED NBDExtendedReplyChunk;
119d95ffb6fSEric Blake 
120d2febedbSVladimir Sementsov-Ogievskiy typedef union NBDReply {
121d2febedbSVladimir Sementsov-Ogievskiy     NBDSimpleReply simple;
122d2febedbSVladimir Sementsov-Ogievskiy     NBDStructuredReplyChunk structured;
123d95ffb6fSEric Blake     NBDExtendedReplyChunk extended;
124d2febedbSVladimir Sementsov-Ogievskiy     struct {
12522efd811SEric Blake         /*
126d95ffb6fSEric Blake          * @magic and @cookie fields have the same offset and size in all
127d95ffb6fSEric Blake          * forms of replies, so let them be accessible without ".simple.",
128d95ffb6fSEric Blake          * ".structured.", or ".extended." specifications.
129d2febedbSVladimir Sementsov-Ogievskiy          */
130d2febedbSVladimir Sementsov-Ogievskiy         uint32_t magic;
131d2febedbSVladimir Sementsov-Ogievskiy         uint32_t _skip;
13222efd811SEric Blake         uint64_t cookie;
133d95ffb6fSEric Blake     };
134d2febedbSVladimir Sementsov-Ogievskiy } NBDReply;
135d95ffb6fSEric Blake QEMU_BUILD_BUG_ON(offsetof(NBDReply, simple.cookie) !=
136d95ffb6fSEric Blake                   offsetof(NBDReply, cookie));
137d95ffb6fSEric Blake QEMU_BUILD_BUG_ON(offsetof(NBDReply, structured.cookie) !=
138d95ffb6fSEric Blake                   offsetof(NBDReply, cookie));
139d95ffb6fSEric Blake QEMU_BUILD_BUG_ON(offsetof(NBDReply, extended.cookie) !=
140d95ffb6fSEric Blake                   offsetof(NBDReply, cookie));
141d2febedbSVladimir Sementsov-Ogievskiy 
142efdc0c10SEric Blake /* Header of chunk for NBD_REPLY_TYPE_OFFSET_DATA */
143efdc0c10SEric Blake typedef struct NBDStructuredReadData {
144a7c8ed36SEric Blake     /* header's .length >= 9 */
145bae245d1SEric Blake     uint64_t offset;
146efdc0c10SEric Blake     /* At least one byte of data payload follows, calculated from h.length */
147efdc0c10SEric Blake } QEMU_PACKED NBDStructuredReadData;
148efdc0c10SEric Blake 
149efdc0c10SEric Blake /* Complete chunk for NBD_REPLY_TYPE_OFFSET_HOLE */
150efdc0c10SEric Blake typedef struct NBDStructuredReadHole {
151a7c8ed36SEric Blake     /* header's length == 12 */
152efdc0c10SEric Blake     uint64_t offset;
153efdc0c10SEric Blake     uint32_t length;
154efdc0c10SEric Blake } QEMU_PACKED NBDStructuredReadHole;
155bae245d1SEric Blake 
156bae245d1SEric Blake /* Header of all NBD_REPLY_TYPE_ERROR* errors */
157bae245d1SEric Blake typedef struct NBDStructuredError {
158a7c8ed36SEric Blake     /* header's length >= 6 */
159bae245d1SEric Blake     uint32_t error;
160bae245d1SEric Blake     uint16_t message_length;
161bae245d1SEric Blake } QEMU_PACKED NBDStructuredError;
162bae245d1SEric Blake 
16325c14678SVladimir Sementsov-Ogievskiy /* Header of NBD_REPLY_TYPE_BLOCK_STATUS */
16425c14678SVladimir Sementsov-Ogievskiy typedef struct NBDStructuredMeta {
165a7c8ed36SEric Blake     /* header's length >= 12 (at least one extent) */
16625c14678SVladimir Sementsov-Ogievskiy     uint32_t context_id;
167d95ffb6fSEric Blake     /* NBDExtent32 extents[] follows, array length implied by header */
16825c14678SVladimir Sementsov-Ogievskiy } QEMU_PACKED NBDStructuredMeta;
16925c14678SVladimir Sementsov-Ogievskiy 
170d95ffb6fSEric Blake /* Extent array element for NBD_REPLY_TYPE_BLOCK_STATUS */
171d95ffb6fSEric Blake typedef struct NBDExtent32 {
17225c14678SVladimir Sementsov-Ogievskiy     uint32_t length;
17325c14678SVladimir Sementsov-Ogievskiy     uint32_t flags; /* NBD_STATE_* */
174d95ffb6fSEric Blake } QEMU_PACKED NBDExtent32;
175d95ffb6fSEric Blake 
176d95ffb6fSEric Blake /* Header of NBD_REPLY_TYPE_BLOCK_STATUS_EXT */
177d95ffb6fSEric Blake typedef struct NBDExtendedMeta {
178d95ffb6fSEric Blake     /* header's length >= 24 (at least one extent) */
179d95ffb6fSEric Blake     uint32_t context_id;
180d95ffb6fSEric Blake     uint32_t count; /* header length must be count * 16 + 8 */
181d95ffb6fSEric Blake     /* NBDExtent64 extents[count] follows */
182d95ffb6fSEric Blake } QEMU_PACKED NBDExtendedMeta;
183d95ffb6fSEric Blake 
184d95ffb6fSEric Blake /* Extent array element for NBD_REPLY_TYPE_BLOCK_STATUS_EXT */
185d95ffb6fSEric Blake typedef struct NBDExtent64 {
186d95ffb6fSEric Blake     uint64_t length;
187d95ffb6fSEric Blake     uint64_t flags; /* NBD_STATE_* */
188d95ffb6fSEric Blake } QEMU_PACKED NBDExtent64;
189d95ffb6fSEric Blake 
190d95ffb6fSEric Blake /* Client payload for limiting NBD_CMD_BLOCK_STATUS reply */
191d95ffb6fSEric Blake typedef struct NBDBlockStatusPayload {
192d95ffb6fSEric Blake     uint64_t effect_length;
193d95ffb6fSEric Blake     /* uint32_t ids[] follows, array length implied by header */
194d95ffb6fSEric Blake } QEMU_PACKED NBDBlockStatusPayload;
19525c14678SVladimir Sementsov-Ogievskiy 
196b626b51aSEric Blake /* Transmission (export) flags: sent from server to client during handshake,
197b626b51aSEric Blake    but describe what will happen during transmission */
198c4e2aff8SMax Reitz enum {
199c4e2aff8SMax Reitz     NBD_FLAG_HAS_FLAGS_BIT          =  0, /* Flags are there */
200c4e2aff8SMax Reitz     NBD_FLAG_READ_ONLY_BIT          =  1, /* Device is read-only */
201c4e2aff8SMax Reitz     NBD_FLAG_SEND_FLUSH_BIT         =  2, /* Send FLUSH */
202c4e2aff8SMax Reitz     NBD_FLAG_SEND_FUA_BIT           =  3, /* Send FUA (Force Unit Access) */
203c4e2aff8SMax Reitz     NBD_FLAG_ROTATIONAL_BIT         =  4, /* Use elevator algorithm -
20492652b12SVladimir Sementsov-Ogievskiy                                              rotational media */
205c4e2aff8SMax Reitz     NBD_FLAG_SEND_TRIM_BIT          =  5, /* Send TRIM (discard) */
206c4e2aff8SMax Reitz     NBD_FLAG_SEND_WRITE_ZEROES_BIT  =  6, /* Send WRITE_ZEROES */
207c4e2aff8SMax Reitz     NBD_FLAG_SEND_DF_BIT            =  7, /* Send DF (Do not Fragment) */
208c4e2aff8SMax Reitz     NBD_FLAG_CAN_MULTI_CONN_BIT     =  8, /* Multi-client cache consistent */
209c4e2aff8SMax Reitz     NBD_FLAG_SEND_RESIZE_BIT        =  9, /* Send resize */
210c4e2aff8SMax Reitz     NBD_FLAG_SEND_CACHE_BIT         = 10, /* Send CACHE (prefetch) */
2110a479545SEric Blake     NBD_FLAG_SEND_FAST_ZERO_BIT     = 11, /* FAST_ZERO flag for WRITE_ZEROES */
212d95ffb6fSEric Blake     NBD_FLAG_BLOCK_STAT_PAYLOAD_BIT = 12, /* PAYLOAD flag for BLOCK_STATUS */
213c4e2aff8SMax Reitz };
214c4e2aff8SMax Reitz 
215c4e2aff8SMax Reitz #define NBD_FLAG_HAS_FLAGS          (1 << NBD_FLAG_HAS_FLAGS_BIT)
216c4e2aff8SMax Reitz #define NBD_FLAG_READ_ONLY          (1 << NBD_FLAG_READ_ONLY_BIT)
217c4e2aff8SMax Reitz #define NBD_FLAG_SEND_FLUSH         (1 << NBD_FLAG_SEND_FLUSH_BIT)
218c4e2aff8SMax Reitz #define NBD_FLAG_SEND_FUA           (1 << NBD_FLAG_SEND_FUA_BIT)
219c4e2aff8SMax Reitz #define NBD_FLAG_ROTATIONAL         (1 << NBD_FLAG_ROTATIONAL_BIT)
220c4e2aff8SMax Reitz #define NBD_FLAG_SEND_TRIM          (1 << NBD_FLAG_SEND_TRIM_BIT)
221c4e2aff8SMax Reitz #define NBD_FLAG_SEND_WRITE_ZEROES  (1 << NBD_FLAG_SEND_WRITE_ZEROES_BIT)
222c4e2aff8SMax Reitz #define NBD_FLAG_SEND_DF            (1 << NBD_FLAG_SEND_DF_BIT)
223c4e2aff8SMax Reitz #define NBD_FLAG_CAN_MULTI_CONN     (1 << NBD_FLAG_CAN_MULTI_CONN_BIT)
224c4e2aff8SMax Reitz #define NBD_FLAG_SEND_RESIZE        (1 << NBD_FLAG_SEND_RESIZE_BIT)
225c4e2aff8SMax Reitz #define NBD_FLAG_SEND_CACHE         (1 << NBD_FLAG_SEND_CACHE_BIT)
2260a479545SEric Blake #define NBD_FLAG_SEND_FAST_ZERO     (1 << NBD_FLAG_SEND_FAST_ZERO_BIT)
227d95ffb6fSEric Blake #define NBD_FLAG_BLOCK_STAT_PAYLOAD (1 << NBD_FLAG_BLOCK_STAT_PAYLOAD_BIT)
228737e150eSPaolo Bonzini 
229b626b51aSEric Blake /* New-style handshake (global) flags, sent from server to client, and
230b626b51aSEric Blake    control what will happen during handshake phase. */
231f5076b5aSHani Benhabiles #define NBD_FLAG_FIXED_NEWSTYLE   (1 << 0) /* Fixed newstyle protocol. */
232c203c59aSEric Blake #define NBD_FLAG_NO_ZEROES        (1 << 1) /* End handshake without zeroes. */
233f5076b5aSHani Benhabiles 
234b626b51aSEric Blake /* New-style client flags, sent from client to server to control what happens
235b626b51aSEric Blake    during handshake phase. */
236f5076b5aSHani Benhabiles #define NBD_FLAG_C_FIXED_NEWSTYLE (1 << 0) /* Fixed newstyle protocol. */
237c203c59aSEric Blake #define NBD_FLAG_C_NO_ZEROES      (1 << 1) /* End handshake without zeroes. */
238f5076b5aSHani Benhabiles 
2393736cc5bSEric Blake /* Option requests. */
2403736cc5bSEric Blake #define NBD_OPT_EXPORT_NAME       (1)
2413736cc5bSEric Blake #define NBD_OPT_ABORT             (2)
2423736cc5bSEric Blake #define NBD_OPT_LIST              (3)
2433736cc5bSEric Blake /* #define NBD_OPT_PEEK_EXPORT    (4) not in use */
2443736cc5bSEric Blake #define NBD_OPT_STARTTLS          (5)
2453736cc5bSEric Blake #define NBD_OPT_INFO              (6)
2463736cc5bSEric Blake #define NBD_OPT_GO                (7)
2473736cc5bSEric Blake #define NBD_OPT_STRUCTURED_REPLY  (8)
24825c14678SVladimir Sementsov-Ogievskiy #define NBD_OPT_LIST_META_CONTEXT (9)
24925c14678SVladimir Sementsov-Ogievskiy #define NBD_OPT_SET_META_CONTEXT  (10)
250d95ffb6fSEric Blake #define NBD_OPT_EXTENDED_HEADERS  (11)
2513736cc5bSEric Blake 
2523736cc5bSEric Blake /* Option reply types. */
253b6f5d3b5SEric Blake #define NBD_REP_ERR(value) ((UINT32_C(1) << 31) | (value))
254b6f5d3b5SEric Blake 
25532d7d2e0SHani Benhabiles #define NBD_REP_ACK             (1)    /* Data sending finished. */
25632d7d2e0SHani Benhabiles #define NBD_REP_SERVER          (2)    /* Export description. */
2573736cc5bSEric Blake #define NBD_REP_INFO            (3)    /* NBD_OPT_INFO/GO. */
25825c14678SVladimir Sementsov-Ogievskiy #define NBD_REP_META_CONTEXT    (4)    /* NBD_OPT_{LIST,SET}_META_CONTEXT */
259b6f5d3b5SEric Blake 
260b6f5d3b5SEric Blake #define NBD_REP_ERR_UNSUP           NBD_REP_ERR(1)  /* Unknown option */
261b6f5d3b5SEric Blake #define NBD_REP_ERR_POLICY          NBD_REP_ERR(2)  /* Server denied */
262b6f5d3b5SEric Blake #define NBD_REP_ERR_INVALID         NBD_REP_ERR(3)  /* Invalid length */
263b6f5d3b5SEric Blake #define NBD_REP_ERR_PLATFORM        NBD_REP_ERR(4)  /* Not compiled in */
264b6f5d3b5SEric Blake #define NBD_REP_ERR_TLS_REQD        NBD_REP_ERR(5)  /* TLS required */
2653736cc5bSEric Blake #define NBD_REP_ERR_UNKNOWN         NBD_REP_ERR(6)  /* Export unknown */
266b6f5d3b5SEric Blake #define NBD_REP_ERR_SHUTDOWN        NBD_REP_ERR(7)  /* Server shutting down */
2673736cc5bSEric Blake #define NBD_REP_ERR_BLOCK_SIZE_REQD NBD_REP_ERR(8)  /* Need INFO_BLOCK_SIZE */
268d95ffb6fSEric Blake #define NBD_REP_ERR_TOO_BIG         NBD_REP_ERR(9)  /* Payload size overflow */
269d95ffb6fSEric Blake #define NBD_REP_ERR_EXT_HEADER_REQD NBD_REP_ERR(10) /* Need extended headers */
2703736cc5bSEric Blake 
2713736cc5bSEric Blake /* Info types, used during NBD_REP_INFO */
2723736cc5bSEric Blake #define NBD_INFO_EXPORT         0
2733736cc5bSEric Blake #define NBD_INFO_NAME           1
2743736cc5bSEric Blake #define NBD_INFO_DESCRIPTION    2
2753736cc5bSEric Blake #define NBD_INFO_BLOCK_SIZE     3
276f95910feSDaniel P. Berrange 
277b626b51aSEric Blake /* Request flags, sent from client to server during transmission phase */
2781f4d6d18SEric Blake #define NBD_CMD_FLAG_FUA         (1 << 0) /* 'force unit access' during write */
2791f4d6d18SEric Blake #define NBD_CMD_FLAG_NO_HOLE     (1 << 1) /* don't punch hole on zero run */
280bae245d1SEric Blake #define NBD_CMD_FLAG_DF          (1 << 2) /* don't fragment structured read */
281d95ffb6fSEric Blake #define NBD_CMD_FLAG_REQ_ONE     (1 << 3) \
282d95ffb6fSEric Blake     /* only one extent in BLOCK_STATUS reply chunk */
2830a479545SEric Blake #define NBD_CMD_FLAG_FAST_ZERO   (1 << 4) /* fail if WRITE_ZEROES is not fast */
284d95ffb6fSEric Blake #define NBD_CMD_FLAG_PAYLOAD_LEN (1 << 5) \
285d95ffb6fSEric Blake     /* length describes payload, not effect; only with ext header */
286f5076b5aSHani Benhabiles 
287b626b51aSEric Blake /* Supported request types */
288737e150eSPaolo Bonzini enum {
289737e150eSPaolo Bonzini     NBD_CMD_READ = 0,
290737e150eSPaolo Bonzini     NBD_CMD_WRITE = 1,
291737e150eSPaolo Bonzini     NBD_CMD_DISC = 2,
292737e150eSPaolo Bonzini     NBD_CMD_FLUSH = 3,
2931f4d6d18SEric Blake     NBD_CMD_TRIM = 4,
294bc37b06aSVladimir Sementsov-Ogievskiy     NBD_CMD_CACHE = 5,
2951f4d6d18SEric Blake     NBD_CMD_WRITE_ZEROES = 6,
29625c14678SVladimir Sementsov-Ogievskiy     NBD_CMD_BLOCK_STATUS = 7,
297737e150eSPaolo Bonzini };
298737e150eSPaolo Bonzini 
299737e150eSPaolo Bonzini #define NBD_DEFAULT_PORT	10809
300737e150eSPaolo Bonzini 
3012d821488SStefan Hajnoczi /* Maximum size of a single READ/WRITE data buffer */
3022d821488SStefan Hajnoczi #define NBD_MAX_BUFFER_SIZE (32 * 1024 * 1024)
303476b923cSEric Blake 
3049d7ab222SEric Blake /*
30571719cd5SEric Blake  * Maximum size of a protocol string (export name, metadata context name,
30693676c88SEric Blake  * etc.).  Use malloc rather than stack allocation for storage of a
30793676c88SEric Blake  * string.
3089d7ab222SEric Blake  */
30993676c88SEric Blake #define NBD_MAX_STRING_SIZE 4096
310737e150eSPaolo Bonzini 
311d95ffb6fSEric Blake /* Two types of request structures, a given client will only use 1 */
312d95ffb6fSEric Blake #define NBD_REQUEST_MAGIC           0x25609513
313d95ffb6fSEric Blake #define NBD_EXTENDED_REQUEST_MAGIC  0x21e41c71
314d95ffb6fSEric Blake 
315d95ffb6fSEric Blake /*
316d95ffb6fSEric Blake  * Three types of reply structures, but what a client expects depends
317d95ffb6fSEric Blake  * on NBD_OPT_STRUCTURED_REPLY and NBD_OPT_EXTENDED_HEADERS.
318d95ffb6fSEric Blake  */
319bae245d1SEric Blake #define NBD_SIMPLE_REPLY_MAGIC      0x67446698
320bae245d1SEric Blake #define NBD_STRUCTURED_REPLY_MAGIC  0x668e33ef
321d95ffb6fSEric Blake #define NBD_EXTENDED_REPLY_MAGIC    0x6e8a278c
322bae245d1SEric Blake 
323d95ffb6fSEric Blake /* Chunk reply flags (for structured and extended replies) */
324bae245d1SEric Blake #define NBD_REPLY_FLAG_DONE          (1 << 0) /* This reply-chunk is last */
325bae245d1SEric Blake 
326d95ffb6fSEric Blake /* Chunk reply types */
327bae245d1SEric Blake #define NBD_REPLY_ERR(value)         ((1 << 15) | (value))
328bae245d1SEric Blake 
329bae245d1SEric Blake #define NBD_REPLY_TYPE_NONE              0
330bae245d1SEric Blake #define NBD_REPLY_TYPE_OFFSET_DATA       1
331bae245d1SEric Blake #define NBD_REPLY_TYPE_OFFSET_HOLE       2
33225c14678SVladimir Sementsov-Ogievskiy #define NBD_REPLY_TYPE_BLOCK_STATUS      5
333d95ffb6fSEric Blake #define NBD_REPLY_TYPE_BLOCK_STATUS_EXT  6
334bae245d1SEric Blake #define NBD_REPLY_TYPE_ERROR             NBD_REPLY_ERR(1)
335bae245d1SEric Blake #define NBD_REPLY_TYPE_ERROR_OFFSET      NBD_REPLY_ERR(2)
336bae245d1SEric Blake 
3373d068affSVladimir Sementsov-Ogievskiy /* Extent flags for base:allocation in NBD_REPLY_TYPE_BLOCK_STATUS */
33825c14678SVladimir Sementsov-Ogievskiy #define NBD_STATE_HOLE (1 << 0)
33925c14678SVladimir Sementsov-Ogievskiy #define NBD_STATE_ZERO (1 << 1)
34025c14678SVladimir Sementsov-Ogievskiy 
3413d068affSVladimir Sementsov-Ogievskiy /* Extent flags for qemu:dirty-bitmap in NBD_REPLY_TYPE_BLOCK_STATUS */
3423d068affSVladimir Sementsov-Ogievskiy #define NBD_STATE_DIRTY (1 << 0)
3433d068affSVladimir Sementsov-Ogievskiy 
34471719cd5SEric Blake /* No flags needed for qemu:allocation-depth in NBD_REPLY_TYPE_BLOCK_STATUS */
34571719cd5SEric Blake 
nbd_reply_type_is_error(int type)346f140e300SVladimir Sementsov-Ogievskiy static inline bool nbd_reply_type_is_error(int type)
347f140e300SVladimir Sementsov-Ogievskiy {
348f140e300SVladimir Sementsov-Ogievskiy     return type & (1 << 15);
349f140e300SVladimir Sementsov-Ogievskiy }
350f140e300SVladimir Sementsov-Ogievskiy 
351dd689440SEric Blake /* NBD errors are based on errno numbers, so there is a 1:1 mapping,
352dd689440SEric Blake  * but only a limited set of errno values is specified in the protocol.
353dd689440SEric Blake  * Everything else is squashed to EINVAL.
354dd689440SEric Blake  */
355dd689440SEric Blake #define NBD_SUCCESS    0
356dd689440SEric Blake #define NBD_EPERM      1
357dd689440SEric Blake #define NBD_EIO        5
358dd689440SEric Blake #define NBD_ENOMEM     12
359dd689440SEric Blake #define NBD_EINVAL     22
360dd689440SEric Blake #define NBD_ENOSPC     28
361bae245d1SEric Blake #define NBD_EOVERFLOW  75
3620a479545SEric Blake #define NBD_ENOTSUP    95
363dd689440SEric Blake #define NBD_ESHUTDOWN  108
364dd689440SEric Blake 
365004a89fcSEric Blake /* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */
3668d2931dcSEric Blake typedef struct NBDExportInfo {
367081dd1feSEric Blake     /* Set by client before nbd_receive_negotiate() */
368081dd1feSEric Blake     bool request_sizes;
369216ee365SEric Blake     char *x_dirty_bitmap;
370d21a2d34SEric Blake 
371d21a2d34SEric Blake     /* Set by client before nbd_receive_negotiate(), or by server results
372d21a2d34SEric Blake      * during nbd_receive_export_list() */
3736dc1667dSEric Blake     char *name; /* must be non-NULL */
374f140e300SVladimir Sementsov-Ogievskiy 
375f140e300SVladimir Sementsov-Ogievskiy     /* In-out fields, set by client before nbd_receive_negotiate() and
376f140e300SVladimir Sementsov-Ogievskiy      * updated by server results during nbd_receive_negotiate() */
377ac132d05SEric Blake     NBDMode mode; /* input maximum mode tolerated; output actual mode chosen */
37878a33ab5SVladimir Sementsov-Ogievskiy     bool base_allocation; /* base:allocation context for NBD_CMD_BLOCK_STATUS */
379f140e300SVladimir Sementsov-Ogievskiy 
380d21a2d34SEric Blake     /* Set by server results during nbd_receive_negotiate() and
381d21a2d34SEric Blake      * nbd_receive_export_list() */
382004a89fcSEric Blake     uint64_t size;
383004a89fcSEric Blake     uint16_t flags;
384081dd1feSEric Blake     uint32_t min_block;
385081dd1feSEric Blake     uint32_t opt_block;
386081dd1feSEric Blake     uint32_t max_block;
38778a33ab5SVladimir Sementsov-Ogievskiy 
3882df94eb5SEric Blake     uint32_t context_id;
389d21a2d34SEric Blake 
390d21a2d34SEric Blake     /* Set by server results during nbd_receive_export_list() */
391d21a2d34SEric Blake     char *description;
3920b576b6bSEric Blake     int n_contexts;
3930b576b6bSEric Blake     char **contexts;
3948d2931dcSEric Blake } NBDExportInfo;
395004a89fcSEric Blake 
396b84ca91cSStefan Hajnoczi int nbd_receive_negotiate(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
3976dc1667dSEric Blake                           const char *hostname, QIOChannel **outioc,
3986dc1667dSEric Blake                           NBDExportInfo *info, Error **errp);
399d21a2d34SEric Blake void nbd_free_export_list(NBDExportInfo *info, int count);
400d21a2d34SEric Blake int nbd_receive_export_list(QIOChannel *ioc, QCryptoTLSCreds *tlscreds,
401d21a2d34SEric Blake                             const char *hostname, NBDExportInfo **info,
402d21a2d34SEric Blake                             Error **errp);
403004a89fcSEric Blake int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
404be41c100SVladimir Sementsov-Ogievskiy              Error **errp);
405490dc5edSVladimir Sementsov-Ogievskiy int nbd_send_request(QIOChannel *ioc, NBDRequest *request);
406d3bd5b90SKevin Wolf int coroutine_fn nbd_receive_reply(BlockDriverState *bs, QIOChannel *ioc,
4074fc55bf3SEric Blake                                    NBDReply *reply, NBDMode mode,
4084fc55bf3SEric Blake                                    Error **errp);
409737e150eSPaolo Bonzini int nbd_client(int fd);
410737e150eSPaolo Bonzini int nbd_disconnect(int fd);
411dd689440SEric Blake int nbd_errno_to_system_errno(int err);
412737e150eSPaolo Bonzini 
4139b562c64SKevin Wolf void nbd_export_set_on_eject_blk(BlockExport *exp, BlockBackend *blk);
414737e150eSPaolo Bonzini 
41561bc846dSEric Blake AioContext *nbd_export_aio_context(NBDExport *exp);
416737e150eSPaolo Bonzini NBDExport *nbd_export_find(const char *name);
417737e150eSPaolo Bonzini 
4187f7dfe2aSVladimir Sementsov-Ogievskiy void nbd_client_new(QIOChannelSocket *sioc,
419fb1c2aaaSEric Blake                     uint32_t handshake_max_secs,
420f95910feSDaniel P. Berrange                     QCryptoTLSCreds *tlscreds,
421b25e12daSDaniel P. Berrange                     const char *tlsauthz,
422fb1c2aaaSEric Blake                     void (*close_fn)(NBDClient *, bool),
423fb1c2aaaSEric Blake                     void *owner);
424fb1c2aaaSEric Blake void *nbd_client_owner(NBDClient *client);
425737e150eSPaolo Bonzini void nbd_client_get(NBDClient *client);
426737e150eSPaolo Bonzini void nbd_client_put(NBDClient *client);
427737e150eSPaolo Bonzini 
428a5fced40SEric Blake void nbd_server_is_qemu_nbd(int max_connections);
4295b1cb497SKevin Wolf bool nbd_server_is_running(void);
43058a6fdccSEric Blake int nbd_server_max_connections(void);
431bd269ebcSMarkus Armbruster void nbd_server_start(SocketAddress *addr, const char *tls_creds,
4321c8222b0SKevin Wolf                       const char *tls_authz, uint32_t max_connections,
4331c8222b0SKevin Wolf                       Error **errp);
434eed8b691SKevin Wolf void nbd_server_start_options(NbdServerOptions *arg, Error **errp);
435bd269ebcSMarkus Armbruster 
43656dc682bSEric Blake /* nbd_read
43756dc682bSEric Blake  * Reads @size bytes from @ioc. Returns 0 on success.
43856dc682bSEric Blake  */
nbd_read(QIOChannel * ioc,void * buffer,size_t size,const char * desc,Error ** errp)43956dc682bSEric Blake static inline int nbd_read(QIOChannel *ioc, void *buffer, size_t size,
440e6798f06SVladimir Sementsov-Ogievskiy                            const char *desc, Error **errp)
44156dc682bSEric Blake {
442795d946dSVladimir Sementsov-Ogievskiy     ERRP_GUARD();
443e6798f06SVladimir Sementsov-Ogievskiy     int ret = qio_channel_read_all(ioc, buffer, size, errp) < 0 ? -EIO : 0;
444e6798f06SVladimir Sementsov-Ogievskiy 
445e6798f06SVladimir Sementsov-Ogievskiy     if (ret < 0) {
446e6798f06SVladimir Sementsov-Ogievskiy         if (desc) {
447e6798f06SVladimir Sementsov-Ogievskiy             error_prepend(errp, "Failed to read %s: ", desc);
44856dc682bSEric Blake         }
4495082fc82SRoman Kagan         return ret;
450e6798f06SVladimir Sementsov-Ogievskiy     }
451e6798f06SVladimir Sementsov-Ogievskiy 
452e6798f06SVladimir Sementsov-Ogievskiy     return 0;
453e6798f06SVladimir Sementsov-Ogievskiy }
454e6798f06SVladimir Sementsov-Ogievskiy 
455e6798f06SVladimir Sementsov-Ogievskiy #define DEF_NBD_READ_N(bits)                                            \
456e6798f06SVladimir Sementsov-Ogievskiy static inline int nbd_read##bits(QIOChannel *ioc,                       \
457e6798f06SVladimir Sementsov-Ogievskiy                                  uint##bits##_t *val,                   \
458e6798f06SVladimir Sementsov-Ogievskiy                                  const char *desc, Error **errp)        \
459e6798f06SVladimir Sementsov-Ogievskiy {                                                                       \
4605082fc82SRoman Kagan     int ret = nbd_read(ioc, val, sizeof(*val), desc, errp);             \
4615082fc82SRoman Kagan     if (ret < 0) {                                                      \
4625082fc82SRoman Kagan         return ret;                                                     \
463e6798f06SVladimir Sementsov-Ogievskiy     }                                                                   \
464e6798f06SVladimir Sementsov-Ogievskiy     *val = be##bits##_to_cpu(*val);                                     \
465e6798f06SVladimir Sementsov-Ogievskiy     return 0;                                                           \
466e6798f06SVladimir Sementsov-Ogievskiy }
467e6798f06SVladimir Sementsov-Ogievskiy 
468e6798f06SVladimir Sementsov-Ogievskiy DEF_NBD_READ_N(16) /* Defines nbd_read16(). */
469e6798f06SVladimir Sementsov-Ogievskiy DEF_NBD_READ_N(32) /* Defines nbd_read32(). */
470e6798f06SVladimir Sementsov-Ogievskiy DEF_NBD_READ_N(64) /* Defines nbd_read64(). */
471e6798f06SVladimir Sementsov-Ogievskiy 
472e6798f06SVladimir Sementsov-Ogievskiy #undef DEF_NBD_READ_N
47356dc682bSEric Blake 
nbd_reply_is_simple(NBDReply * reply)474d2febedbSVladimir Sementsov-Ogievskiy static inline bool nbd_reply_is_simple(NBDReply *reply)
475d2febedbSVladimir Sementsov-Ogievskiy {
476d2febedbSVladimir Sementsov-Ogievskiy     return reply->magic == NBD_SIMPLE_REPLY_MAGIC;
477d2febedbSVladimir Sementsov-Ogievskiy }
478d2febedbSVladimir Sementsov-Ogievskiy 
nbd_reply_is_structured(NBDReply * reply)479d2febedbSVladimir Sementsov-Ogievskiy static inline bool nbd_reply_is_structured(NBDReply *reply)
480d2febedbSVladimir Sementsov-Ogievskiy {
481d2febedbSVladimir Sementsov-Ogievskiy     return reply->magic == NBD_STRUCTURED_REPLY_MAGIC;
482d2febedbSVladimir Sementsov-Ogievskiy }
483d2febedbSVladimir Sementsov-Ogievskiy 
484f140e300SVladimir Sementsov-Ogievskiy const char *nbd_reply_type_lookup(uint16_t type);
485757a0d05SVladimir Sementsov-Ogievskiy const char *nbd_opt_lookup(uint32_t opt);
486757a0d05SVladimir Sementsov-Ogievskiy const char *nbd_rep_lookup(uint32_t rep);
487757a0d05SVladimir Sementsov-Ogievskiy const char *nbd_info_lookup(uint16_t info);
488757a0d05SVladimir Sementsov-Ogievskiy const char *nbd_cmd_lookup(uint16_t info);
489757a0d05SVladimir Sementsov-Ogievskiy const char *nbd_err_lookup(int err);
490bfe04d0aSEric Blake const char *nbd_mode_lookup(NBDMode mode);
491f140e300SVladimir Sementsov-Ogievskiy 
4925276c87cSVladimir Sementsov-Ogievskiy /* nbd/client-connection.c */
493e0e67cbeSVladimir Sementsov-Ogievskiy void nbd_client_connection_enable_retry(NBDClientConnection *conn);
494e0e67cbeSVladimir Sementsov-Ogievskiy 
495130d49baSVladimir Sementsov-Ogievskiy NBDClientConnection *nbd_client_connection_new(const SocketAddress *saddr,
496130d49baSVladimir Sementsov-Ogievskiy                                                bool do_negotiation,
497130d49baSVladimir Sementsov-Ogievskiy                                                const char *export_name,
498130d49baSVladimir Sementsov-Ogievskiy                                                const char *x_dirty_bitmap,
499046f98d0SDaniel P. Berrangé                                                QCryptoTLSCreds *tlscreds,
500046f98d0SDaniel P. Berrangé                                                const char *tlshostname);
5015276c87cSVladimir Sementsov-Ogievskiy void nbd_client_connection_release(NBDClientConnection *conn);
5025276c87cSVladimir Sementsov-Ogievskiy 
50343cb34deSVladimir Sementsov-Ogievskiy QIOChannel *coroutine_fn
504130d49baSVladimir Sementsov-Ogievskiy nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info,
50597cf8925SVladimir Sementsov-Ogievskiy                             bool blocking, Error **errp);
5065276c87cSVladimir Sementsov-Ogievskiy 
5079fb26291SPaolo Bonzini void nbd_co_establish_connection_cancel(NBDClientConnection *conn);
5085276c87cSVladimir Sementsov-Ogievskiy 
509737e150eSPaolo Bonzini #endif
510