Line data Source code
1 : /*
2 : * vr_uvhost_util.c - utils for user-space vhost server that peers with
3 : * the vhost client inside qemu (version 2.1 and later).
4 : *
5 : * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
6 : */
7 :
8 : #include "vr_dpdk.h"
9 : #include "vr_uvhost_util.h"
10 :
11 : typedef struct uvh_fd_s {
12 : int uvh_fd;
13 : void *uvh_fd_arg;
14 : uvh_fd_handler_t uvh_fd_fn;
15 : } uvh_fd_t;
16 :
17 : /* Global variables */
18 : static uvh_fd_t uvh_rfds[MAX_UVHOST_FDS];
19 : static uvh_fd_t uvh_wfds[MAX_UVHOST_FDS];
20 :
21 : /*
22 : * vr_uvhost_log - logs user space vhost messages to a file.
23 : */
24 : void
25 8452 : vr_uvhost_log(const char *format, ...)
26 : {
27 : va_list args;
28 :
29 8452 : if (RTE_LOGTYPE_UVHOST & rte_logs.type) {
30 8452 : char buf[VR_DPDK_STR_BUF_SZ] = "UVHOST: ";
31 :
32 8452 : strncat(buf, format, sizeof(buf) - strlen(buf) - 1);
33 8452 : buf[sizeof(buf) - 1] = '\0';
34 :
35 8452 : va_start(args, format);
36 8452 : rte_vlog(RTE_LOG_INFO, RTE_LOGTYPE_UVHOST, buf, args);
37 8452 : va_end(args);
38 : }
39 8452 : }
40 :
41 : /*
42 : * vr_uvhost_del_fd - deletes a FD from the read/write list that the
43 : * user space vhost server is listening on. fd_type indicates if it
44 : * is a read/write socket. The FD passed in will be closed.
45 : *
46 : * Returns 0 on success, -1 otherwise.
47 : */
48 : int
49 596 : vr_uvhost_del_fd(int fd, uvh_fd_type_t fd_type)
50 : {
51 : int i;
52 : uvh_fd_t *fds;
53 :
54 : RTE_LOG_DP(DEBUG, UVHOST, "Deleting FD %d...\n", fd);
55 596 : if (fd_type == UVH_FD_READ) {
56 596 : fds = uvh_rfds;
57 0 : } else if (fd_type == UVH_FD_WRITE) {
58 0 : fds = uvh_wfds;
59 : } else {
60 0 : return -1;
61 : }
62 :
63 3608 : for (i = 0; i < MAX_UVHOST_FDS; i++) {
64 3608 : if (fds[i].uvh_fd == fd) {
65 596 : break;
66 : }
67 : }
68 :
69 596 : if (i == MAX_UVHOST_FDS) {
70 : /* The descriptor could be deleted on read error, so no need to
71 : * print the error message.
72 : */
73 0 : return -1;
74 : }
75 :
76 596 : fds[i].uvh_fd = -1;
77 596 : fds[i].uvh_fd_arg = NULL;
78 :
79 596 : close(fd);
80 :
81 596 : return 0;
82 : }
83 :
84 : /*
85 : * vr_uvhost_del_fds_by_arg - deletes all FDs from the read/write lists matching
86 : * the given argument (pointer to a client). All the FDs found will be closed.
87 : *
88 : * Returns 0 on success, -1 otherwise.
89 : */
90 : int
91 166 : vr_uvhost_del_fds_by_arg(void *arg)
92 : {
93 : int i;
94 :
95 723096 : for (i = 0; i < MAX_UVHOST_FDS; i++) {
96 722930 : if (uvh_rfds[i].uvh_fd > 0 && uvh_rfds[i].uvh_fd_arg == arg)
97 181 : vr_uvhost_del_fd(uvh_rfds[i].uvh_fd, UVH_FD_READ);
98 722930 : if (uvh_wfds[i].uvh_fd > 0 && uvh_wfds[i].uvh_fd_arg == arg)
99 0 : vr_uvhost_del_fd(uvh_wfds[i].uvh_fd, UVH_FD_WRITE);
100 : }
101 :
102 166 : return 0;
103 : }
104 :
105 : /*
106 : * vr_uvhost_add_fd - adds the specified FD into the read/write list that
107 : * the user space vhost server is waiting on. The type indicates if it
108 : * is a read/write socket and the handler is the function that is called when
109 : * there is an event on the socket.
110 : *
111 : * Returns 0 on success, -1 otherwise.
112 : */
113 : int
114 1294 : vr_uvhost_add_fd(int fd, uvh_fd_type_t fd_type, void *fd_handler_arg,
115 : uvh_fd_handler_t fd_handler)
116 : {
117 : int i;
118 : uvh_fd_t *fds;
119 :
120 : RTE_LOG_DP(DEBUG, UVHOST, "Adding FD %d...\n", fd);
121 1294 : if (fd_type == UVH_FD_READ) {
122 1294 : fds = uvh_rfds;
123 0 : } else if (fd_type == UVH_FD_WRITE) {
124 0 : fds = uvh_wfds;
125 : } else {
126 0 : return -1;
127 : }
128 :
129 7094 : for (i = 0; i < MAX_UVHOST_FDS; i++) {
130 7094 : if (fds[i].uvh_fd == fd || fds[i].uvh_fd == -1) {
131 1294 : fds[i].uvh_fd = fd;
132 1294 : fds[i].uvh_fd_arg = fd_handler_arg;
133 1294 : fds[i].uvh_fd_fn = fd_handler;
134 :
135 1294 : return 0;
136 : }
137 : }
138 :
139 0 : vr_uvhost_log("Error adding FD %d: no room for a new FD\n", fd);
140 :
141 0 : return -1;
142 : }
143 :
144 : /*
145 : * vr_uvhost_fds_init - initializes the read and write fds before
146 : * we enter the poll loop.
147 : */
148 : void
149 53 : vr_uvhost_fds_init(void)
150 : {
151 : int i;
152 :
153 230868 : for (i = 0; i < MAX_UVHOST_FDS; i++) {
154 230815 : uvh_rfds[i].uvh_fd = -1;
155 230815 : uvh_wfds[i].uvh_fd = -1;
156 : }
157 :
158 53 : return;
159 : }
160 :
161 : /*
162 : * vr_uvh_call_fd_handlers_internal - call the handler associated with the
163 : * given fd.
164 : *
165 : * Returns 0 on success, -1 otherwise.
166 : */
167 : static int
168 4000 : vr_uvh_call_fd_handlers_internal(uvh_fd_t *fd_arr, int fd)
169 : {
170 4000 : int i, ret = 0;
171 :
172 21562 : for (i = 0; i < MAX_UVHOST_FDS; i++) {
173 21562 : if (fd_arr[i].uvh_fd != fd) {
174 17562 : continue;
175 : }
176 :
177 4000 : ret = fd_arr[i].uvh_fd_fn(fd_arr[i].uvh_fd, fd_arr[i].uvh_fd_arg);
178 4000 : if (ret) {
179 221 : return -1;
180 : } else {
181 3779 : return 0;
182 : }
183 : }
184 :
185 0 : return -1;
186 : }
187 :
188 : /*
189 : * vr_uvh_call_fd_handlers - call the handler for each FD that is set upon
190 : * return from poll().
191 : *
192 : * Returns nothing.
193 : */
194 : void
195 3889 : vr_uvh_call_fd_handlers(struct pollfd *fds, nfds_t nfds)
196 : {
197 : unsigned int i;
198 : int ret;
199 :
200 31270 : for (i = 0; i < nfds; i++) {
201 27381 : if (fds[i].fd >= 0) {
202 27381 : if (fds[i].revents & POLLIN) {
203 4000 : ret = vr_uvh_call_fd_handlers_internal(uvh_rfds, fds[i].fd);
204 4000 : if (ret) {
205 221 : vr_uvhost_del_fd(fds[i].fd, UVH_FD_READ);
206 : }
207 : }
208 : }
209 : }
210 :
211 3889 : return;
212 : }
213 :
214 : /*
215 : * vr_uvh_init_pollfds - initializes the array to pass to poll based on the
216 : * state of the fds.
217 : *
218 : * Returns nothing.
219 : */
220 : void
221 3942 : vr_uvh_init_pollfds(struct pollfd *fds, nfds_t *nfds)
222 : {
223 3942 : unsigned int i, count = 0;
224 :
225 17171352 : for (i = 0; i < MAX_UVHOST_FDS; i++) {
226 17167410 : if (uvh_rfds[i].uvh_fd != -1) {
227 27621 : fds[count].fd = uvh_rfds[i].uvh_fd;
228 27621 : fds[count].events = POLLIN;
229 27621 : count++;
230 : }
231 : }
232 :
233 3942 : *nfds = count;
234 :
235 3942 : return;
236 : }
|