xref: /openbmc/qemu/tests/qtest/libqos/virtio-9p-client.h (revision bee8fda2f9841cc8d76fbe60f65f9aeb29fce1c2)
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 
67 struct V9fsDirent {
68     v9fs_qid qid;
69     uint64_t offset;
70     uint8_t type;
71     char *name;
72     struct V9fsDirent *next;
73 };
74 
75 /* options for 'Twalk' 9p request */
76 typedef struct TWalkOpt {
77     /* 9P client being used (mandatory) */
78     QVirtio9P *client;
79     /* user supplied tag number being returned with response (optional) */
80     uint16_t tag;
81     /* file ID of directory from where walk should start (optional) */
82     uint32_t fid;
83     /* file ID for target directory being walked to (optional) */
84     uint32_t newfid;
85     /* low level variant of path to walk to (optional) */
86     uint16_t nwname;
87     char **wnames;
88     /* high level variant of path to walk to (optional) */
89     const char *path;
90     /* data being received from 9p server as 'Rwalk' response (optional) */
91     struct {
92         uint16_t *nwqid;
93         v9fs_qid **wqid;
94     } rwalk;
95     /* only send Twalk request but not wait for a reply? (optional) */
96     bool requestOnly;
97     /* do we expect an Rlerror response, if yes which error code? (optional) */
98     uint32_t expectErr;
99 } TWalkOpt;
100 
101 /* result of 'Twalk' 9p request */
102 typedef struct TWalkRes {
103     /* file ID of target directory been walked to */
104     uint32_t newfid;
105     /* if requestOnly was set: request object for further processing */
106     P9Req *req;
107 } TWalkRes;
108 
109 /* options for 'Tversion' 9p request */
110 typedef struct TVersionOpt {
111     /* 9P client being used (mandatory) */
112     QVirtio9P *client;
113     /* user supplied tag number being returned with response (optional) */
114     uint16_t tag;
115     /* maximum message size that can be handled by client (optional) */
116     uint32_t msize;
117     /* protocol version (optional) */
118     const char *version;
119     /* only send Tversion request but not wait for a reply? (optional) */
120     bool requestOnly;
121     /* do we expect an Rlerror response, if yes which error code? (optional) */
122     uint32_t expectErr;
123 } TVersionOpt;
124 
125 /* result of 'Tversion' 9p request */
126 typedef struct TVersionRes {
127     /* if requestOnly was set: request object for further processing */
128     P9Req *req;
129 } TVersionRes;
130 
131 void v9fs_set_allocator(QGuestAllocator *t_alloc);
132 void v9fs_memwrite(P9Req *req, const void *addr, size_t len);
133 void v9fs_memskip(P9Req *req, size_t len);
134 void v9fs_memread(P9Req *req, void *addr, size_t len);
135 void v9fs_uint8_read(P9Req *req, uint8_t *val);
136 void v9fs_uint16_write(P9Req *req, uint16_t val);
137 void v9fs_uint16_read(P9Req *req, uint16_t *val);
138 void v9fs_uint32_write(P9Req *req, uint32_t val);
139 void v9fs_uint64_write(P9Req *req, uint64_t val);
140 void v9fs_uint32_read(P9Req *req, uint32_t *val);
141 void v9fs_uint64_read(P9Req *req, uint64_t *val);
142 uint16_t v9fs_string_size(const char *string);
143 void v9fs_string_write(P9Req *req, const char *string);
144 void v9fs_string_read(P9Req *req, uint16_t *len, char **string);
145 P9Req *v9fs_req_init(QVirtio9P *v9p, uint32_t size, uint8_t id,
146                      uint16_t tag);
147 void v9fs_req_send(P9Req *req);
148 void v9fs_req_wait_for_reply(P9Req *req, uint32_t *len);
149 void v9fs_req_recv(P9Req *req, uint8_t id);
150 void v9fs_req_free(P9Req *req);
151 void v9fs_rlerror(P9Req *req, uint32_t *err);
152 TVersionRes v9fs_tversion(TVersionOpt);
153 void v9fs_rversion(P9Req *req, uint16_t *len, char **version);
154 P9Req *v9fs_tattach(QVirtio9P *v9p, uint32_t fid, uint32_t n_uname,
155                     uint16_t tag);
156 void v9fs_rattach(P9Req *req, v9fs_qid *qid);
157 TWalkRes v9fs_twalk(TWalkOpt opt);
158 void v9fs_rwalk(P9Req *req, uint16_t *nwqid, v9fs_qid **wqid);
159 P9Req *v9fs_tgetattr(QVirtio9P *v9p, uint32_t fid, uint64_t request_mask,
160                      uint16_t tag);
161 void v9fs_rgetattr(P9Req *req, v9fs_attr *attr);
162 P9Req *v9fs_treaddir(QVirtio9P *v9p, uint32_t fid, uint64_t offset,
163                      uint32_t count, uint16_t tag);
164 void v9fs_rreaddir(P9Req *req, uint32_t *count, uint32_t *nentries,
165                    struct V9fsDirent **entries);
166 void v9fs_free_dirents(struct V9fsDirent *e);
167 P9Req *v9fs_tlopen(QVirtio9P *v9p, uint32_t fid, uint32_t flags,
168                    uint16_t tag);
169 void v9fs_rlopen(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
170 P9Req *v9fs_twrite(QVirtio9P *v9p, uint32_t fid, uint64_t offset,
171                    uint32_t count, const void *data, uint16_t tag);
172 void v9fs_rwrite(P9Req *req, uint32_t *count);
173 P9Req *v9fs_tflush(QVirtio9P *v9p, uint16_t oldtag, uint16_t tag);
174 void v9fs_rflush(P9Req *req);
175 P9Req *v9fs_tmkdir(QVirtio9P *v9p, uint32_t dfid, const char *name,
176                    uint32_t mode, uint32_t gid, uint16_t tag);
177 void v9fs_rmkdir(P9Req *req, v9fs_qid *qid);
178 P9Req *v9fs_tlcreate(QVirtio9P *v9p, uint32_t fid, const char *name,
179                      uint32_t flags, uint32_t mode, uint32_t gid,
180                      uint16_t tag);
181 void v9fs_rlcreate(P9Req *req, v9fs_qid *qid, uint32_t *iounit);
182 P9Req *v9fs_tsymlink(QVirtio9P *v9p, uint32_t fid, const char *name,
183                      const char *symtgt, uint32_t gid, uint16_t tag);
184 void v9fs_rsymlink(P9Req *req, v9fs_qid *qid);
185 P9Req *v9fs_tlink(QVirtio9P *v9p, uint32_t dfid, uint32_t fid,
186                   const char *name, uint16_t tag);
187 void v9fs_rlink(P9Req *req);
188 P9Req *v9fs_tunlinkat(QVirtio9P *v9p, uint32_t dirfd, const char *name,
189                       uint32_t flags, uint16_t tag);
190 void v9fs_runlinkat(P9Req *req);
191 
192 #endif
193