xref: /openbmc/qemu/tests/qtest/libqos/virtio-9p-client.h (revision 2af5be47b9ba264f31f5594e587207cd854e01cc)
1 /*
2  * 9P network client for VirtIO 9P test cases (based on QTest)
3  *
4  * Copyright (c) 2014 SUSE LINUX Products GmbH
5  *
6  * This work is licensed under the terms of the GNU GPL, version 2 or later.
7  * See the COPYING file in the top-level directory.
8  */
9 
10 /*
11  * Not so fast! You might want to read the 9p developer docs first:
12  * https://wiki.qemu.org/Documentation/9p
13  */
14 
15 #ifndef TESTS_LIBQOS_VIRTIO_9P_CLIENT_H
16 #define TESTS_LIBQOS_VIRTIO_9P_CLIENT_H
17 
18 #include "hw/9pfs/9p.h"
19 #include "hw/9pfs/9p-synth.h"
20 #include "virtio-9p.h"
21 #include "qgraph.h"
22 #include "tests/qtest/libqtest-single.h"
23 
24 #define P9_MAX_SIZE 4096 /* Max size of a T-message or R-message */
25 
26 typedef struct {
27     QTestState *qts;
28     QVirtio9P *v9p;
29     uint16_t tag;
30     uint64_t t_msg;
31     uint32_t t_size;
32     uint64_t r_msg;
33     /* No r_size, it is hardcoded to P9_MAX_SIZE */
34     size_t t_off;
35     size_t r_off;
36     uint32_t free_head;
37 } P9Req;
38 
39 /* type[1] version[4] path[8] */
40 typedef char v9fs_qid[13];
41 
42 typedef struct v9fs_attr {
43     uint64_t valid;
44     v9fs_qid qid;
45     uint32_t mode;
46     uint32_t uid;
47     uint32_t gid;
48     uint64_t nlink;
49     uint64_t rdev;
50     uint64_t size;
51     uint64_t blksize;
52     uint64_t blocks;
53     uint64_t atime_sec;
54     uint64_t atime_nsec;
55     uint64_t mtime_sec;
56     uint64_t mtime_nsec;
57     uint64_t ctime_sec;
58     uint64_t ctime_nsec;
59     uint64_t btime_sec;
60     uint64_t btime_nsec;
61     uint64_t gen;
62     uint64_t data_version;
63 } v9fs_attr;
64 
65 #define P9_GETATTR_BASIC    0x000007ffULL /* Mask for fields up to BLOCKS */
66 #define P9_GETATTR_ALL      0x00003fffULL /* Mask for ALL fields */
67 
68 struct V9fsDirent {
69     v9fs_qid qid;
70     uint64_t offset;
71     uint8_t type;
72     char *name;
73     struct V9fsDirent *next;
74 };
75 
76 /* options for 'Twalk' 9p request */
77 typedef struct TWalkOpt {
78     /* 9P client being used (mandatory) */
79     QVirtio9P *client;
80     /* user supplied tag number being returned with response (optional) */
81     uint16_t tag;
82     /* file ID of directory from where walk should start (optional) */
83     uint32_t fid;
84     /* file ID for target directory being walked to (optional) */
85     uint32_t newfid;
86     /* low level variant of path to walk to (optional) */
87     uint16_t nwname;
88     char **wnames;
89     /* high level variant of path to walk to (optional) */
90     const char *path;
91     /* data being received from 9p server as 'Rwalk' response (optional) */
92     struct {
93         uint16_t *nwqid;
94         v9fs_qid **wqid;
95     } rwalk;
96     /* only send Twalk request but not wait for a reply? (optional) */
97     bool requestOnly;
98     /* do we expect an Rlerror response, if yes which error code? (optional) */
99     uint32_t expectErr;
100 } TWalkOpt;
101 
102 /* result of 'Twalk' 9p request */
103 typedef struct TWalkRes {
104     /* file ID of target directory been walked to */
105     uint32_t newfid;
106     /* if requestOnly was set: request object for further processing */
107     P9Req *req;
108 } TWalkRes;
109 
110 /* options for 'Tversion' 9p request */
111 typedef struct TVersionOpt {
112     /* 9P client being used (mandatory) */
113     QVirtio9P *client;
114     /* user supplied tag number being returned with response (optional) */
115     uint16_t tag;
116     /* maximum message size that can be handled by client (optional) */
117     uint32_t msize;
118     /* protocol version (optional) */
119     const char *version;
120     /* only send Tversion request but not wait for a reply? (optional) */
121     bool requestOnly;
122     /* do we expect an Rlerror response, if yes which error code? (optional) */
123     uint32_t expectErr;
124 } TVersionOpt;
125 
126 /* result of 'Tversion' 9p request */
127 typedef struct TVersionRes {
128     /* if requestOnly was set: request object for further processing */
129     P9Req *req;
130 } TVersionRes;
131 
132 /* options for 'Tattach' 9p request */
133 typedef struct TAttachOpt {
134     /* 9P client being used (mandatory) */
135     QVirtio9P *client;
136     /* user supplied tag number being returned with response (optional) */
137     uint16_t tag;
138     /* file ID to be associated with root of file tree (optional) */
139     uint32_t fid;
140     /* numerical uid of user being introduced to server (optional) */
141     uint32_t n_uname;
142     /* data being received from 9p server as 'Rattach' response (optional) */
143     struct {
144         /* server's idea of the root of the file tree */
145         v9fs_qid *qid;
146     } rattach;
147     /* only send Tattach request but not wait for a reply? (optional) */
148     bool requestOnly;
149     /* do we expect an Rlerror response, if yes which error code? (optional) */
150     uint32_t expectErr;
151 } TAttachOpt;
152 
153 /* result of 'Tattach' 9p request */
154 typedef struct TAttachRes {
155     /* if requestOnly was set: request object for further processing */
156     P9Req *req;
157 } TAttachRes;
158 
159 /* options for 'Tgetattr' 9p request */
160 typedef struct TGetAttrOpt {
161     /* 9P client being used (mandatory) */
162     QVirtio9P *client;
163     /* user supplied tag number being returned with response (optional) */
164     uint16_t tag;
165     /* file ID of file/dir whose attributes shall be retrieved (required) */
166     uint32_t fid;
167     /* bitmask indicating attribute fields to be retrieved (optional) */
168     uint64_t request_mask;
169     /* data being received from 9p server as 'Rgetattr' response (optional) */
170     struct {
171         v9fs_attr *attr;
172     } rgetattr;
173     /* only send Tgetattr request but not wait for a reply? (optional) */
174     bool requestOnly;
175     /* do we expect an Rlerror response, if yes which error code? (optional) */
176     uint32_t expectErr;
177 } TGetAttrOpt;
178 
179 /* result of 'Tgetattr' 9p request */
180 typedef struct TGetAttrRes {
181     /* if requestOnly was set: request object for further processing */
182     P9Req *req;
183 } TGetAttrRes;
184 
185 void v9fs_set_allocator(QGuestAllocator *t_alloc);
186 void v9fs_memwrite(P9Req *req, const void *addr, size_t len);
187 void v9fs_memskip(P9Req *req, size_t len);
188 void v9fs_memread(P9Req *req, void *addr, size_t len);
189 void v9fs_uint8_read(P9Req *req, uint8_t *val);
190 void v9fs_uint16_write(P9Req *req, uint16_t val);
191 void v9fs_uint16_read(P9Req *req, uint16_t *val);
192 void v9fs_uint32_write(P9Req *req, uint32_t val);
193 void v9fs_uint64_write(P9Req *req, uint64_t val);
194 void v9fs_uint32_read(P9Req *req, uint32_t *val);
195 void v9fs_uint64_read(P9Req *req, uint64_t *val);
196 uint16_t v9fs_string_size(const char *string);
197 void v9fs_string_write(P9Req *req, const char *string);
198 void v9fs_string_read(P9Req *req, uint16_t *len, char **string);
199 P9Req *v9fs_req_init(QVirtio9P *v9p, uint32_t size, uint8_t id,
200                      uint16_t tag);
201 void v9fs_req_send(P9Req *req);
202 void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len);
203 void v9fs_req_recv(P9Req *req, uint8_t id);
204 void v9fs_req_free(P9Req *req);
205 void v9fs_rlerror(P9Req *req, uint32_t *err);
206 TVersionRes v9fs_tversion(TVersionOpt);
207 void v9fs_rversion(P9Req *req, uint16_t *len, char **version);
208 TAttachRes v9fs_tattach(TAttachOpt);
209 void v9fs_rattach(P9Req *req, v9fs_qid *qid);
210 TWalkRes v9fs_twalk(TWalkOpt opt);
211 void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid);
212 TGetAttrRes v9fs_tgetattr(TGetAttrOpt);
213 void v9fs_rgetattr(P9Req *req, v9fs_attr *attr);
214 P9Req *v9fs_treaddir(QVirtio9P *v9p, uint32_t fid, uint64_t offset,
215                      uint32_t count, uint16_t tag);
216 void v9fs_rreaddir(P9Req *req, uint32_t *count, uint32_t *nentries,
217                    struct V9fsDirent **entries);
218 void v9fs_free_dirents(struct V9fsDirent *e);
219 P9Req *v9fs_tlopen(QVirtio9P *v9p, uint32_t fid, uint32_t flags,
220                    uint16_t tag);
221 void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
222 P9Req *v9fs_twrite(QVirtio9P *v9p, uint32_t fid, uint64_t offset,
223                    uint32_t count, const void *data, uint16_t tag);
224 void v9fs_rwrite(P9Req *req, uint32_t *count);
225 P9Req *v9fs_tflush(QVirtio9P *v9p, uint16_t oldtag, uint16_t tag);
226 void v9fs_rflush(P9Req *req);
227 P9Req *v9fs_tmkdir(QVirtio9P *v9p, uint32_t dfid, const char *name,
228                    uint32_t mode, uint32_t gid, uint16_t tag);
229 void v9fs_rmkdir(P9Req *req, v9fs_qid *qid);
230 P9Req *v9fs_tlcreate(QVirtio9P *v9p, uint32_t fid, const char *name,
231                      uint32_t flags, uint32_t mode, uint32_t gid,
232                      uint16_t tag);
233 void v9fs_rlcreate(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
234 P9Req *v9fs_tsymlink(QVirtio9P *v9p, uint32_t fid, const char *name,
235                      const char *symtgt, uint32_t gid, uint16_t tag);
236 void v9fs_rsymlink(P9Req *req, v9fs_qid *qid);
237 P9Req *v9fs_tlink(QVirtio9P *v9p, uint32_t dfid, uint32_t fid,
238                   const char *name, uint16_t tag);
239 void v9fs_rlink(P9Req *req);
240 P9Req *v9fs_tunlinkat(QVirtio9P *v9p, uint32_t dirfd, const char *name,
241                       uint32_t flags, uint16_t tag);
242 void v9fs_runlinkat(P9Req *req);
243 
244 #endif
245