Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2016 Nicira, Inc.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at:
7 : : *
8 : : * http://www.apache.org/licenses/LICENSE-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : #include <config.h>
18 : : #include <errno.h>
19 : : #include <poll.h>
20 : : #include <stdlib.h>
21 : : #include <string.h>
22 : : #include <sys/types.h>
23 : : #include <unistd.h>
24 : : #include "fatal-signal.h"
25 : : #include "openvswitch/ofpbuf.h"
26 : : #include "openflow/openflow.h"
27 : : #include "poll-loop.h"
28 : : #include "socket-util.h"
29 : : #include "stream.h"
30 : : #include "util.h"
31 : : #include "vconn-provider.h"
32 : : #include "openvswitch/vconn.h"
33 : : #include "openvswitch/vlog.h"
34 : :
35 : 19636 : VLOG_DEFINE_THIS_MODULE(vconn_stream);
36 : :
37 : : /* Active stream socket vconn. */
38 : :
39 : : struct vconn_stream
40 : : {
41 : : struct vconn vconn;
42 : : struct stream *stream;
43 : : struct ofpbuf *rxbuf;
44 : : struct ofpbuf *txbuf;
45 : : int n_packets;
46 : : };
47 : :
48 : : static const struct vconn_class stream_vconn_class;
49 : :
50 : : static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(10, 25);
51 : :
52 : : static void vconn_stream_clear_txbuf(struct vconn_stream *);
53 : :
54 : : static struct vconn *
55 : 6921 : vconn_stream_new(struct stream *stream, int connect_status,
56 : : uint32_t allowed_versions)
57 : : {
58 : : struct vconn_stream *s;
59 : :
60 : 6921 : s = xmalloc(sizeof *s);
61 : 6921 : vconn_init(&s->vconn, &stream_vconn_class, connect_status,
62 : : stream_get_name(stream), allowed_versions);
63 : 6921 : s->stream = stream;
64 : 6921 : s->txbuf = NULL;
65 : 6921 : s->rxbuf = NULL;
66 : 6921 : s->n_packets = 0;
67 : 6921 : return &s->vconn;
68 : : }
69 : :
70 : : /* Creates a new vconn that will send and receive data on a stream named 'name'
71 : : * and stores a pointer to the vconn in '*vconnp'.
72 : : *
73 : : * Returns 0 if successful, otherwise a positive errno value. */
74 : : static int
75 : 6894 : vconn_stream_open(const char *name, uint32_t allowed_versions,
76 : : char *suffix OVS_UNUSED, struct vconn **vconnp, uint8_t dscp)
77 : : {
78 : : struct stream *stream;
79 : : int error;
80 : :
81 : 6894 : error = stream_open_with_default_port(name, OFP_PORT, &stream, dscp);
82 [ + + ]: 6894 : if (!error) {
83 : 3502 : error = stream_connect(stream);
84 [ + + ][ + - ]: 3502 : if (!error || error == EAGAIN) {
85 : 3502 : *vconnp = vconn_stream_new(stream, error, allowed_versions);
86 : 3502 : return 0;
87 : : }
88 : : }
89 : :
90 : 3392 : stream_close(stream);
91 : 6894 : return error;
92 : : }
93 : :
94 : : static struct vconn_stream *
95 : 704825 : vconn_stream_cast(struct vconn *vconn)
96 : : {
97 : 704825 : return CONTAINER_OF(vconn, struct vconn_stream, vconn);
98 : : }
99 : :
100 : : static void
101 : 6870 : vconn_stream_close(struct vconn *vconn)
102 : : {
103 : 6870 : struct vconn_stream *s = vconn_stream_cast(vconn);
104 : :
105 [ + + ][ + + ]: 6870 : if ((vconn->error == EPROTO || s->n_packets < 1) && s->rxbuf) {
[ + + ]
106 : 8 : stream_report_content(s->rxbuf->data, s->rxbuf->size, STREAM_OPENFLOW,
107 : : &this_module, vconn_get_name(vconn));
108 : : }
109 : :
110 : 6870 : stream_close(s->stream);
111 : 6870 : vconn_stream_clear_txbuf(s);
112 : 6870 : ofpbuf_delete(s->rxbuf);
113 : 6870 : free(s);
114 : 6870 : }
115 : :
116 : : static int
117 : 75 : vconn_stream_connect(struct vconn *vconn)
118 : : {
119 : 75 : struct vconn_stream *s = vconn_stream_cast(vconn);
120 : 75 : return stream_connect(s->stream);
121 : : }
122 : :
123 : : static int
124 : 254636 : vconn_stream_recv__(struct vconn_stream *s, int rx_len)
125 : : {
126 : 254636 : struct ofpbuf *rx = s->rxbuf;
127 : : int want_bytes, retval;
128 : :
129 : 254636 : want_bytes = rx_len - rx->size;
130 : 254636 : ofpbuf_prealloc_tailroom(rx, want_bytes);
131 : 254636 : retval = stream_recv(s->stream, ofpbuf_tail(rx), want_bytes);
132 [ + + ]: 254636 : if (retval > 0) {
133 : 125174 : rx->size += retval;
134 [ + - ]: 125174 : return retval == want_bytes ? 0 : EAGAIN;
135 [ + + ]: 129462 : } else if (retval == 0) {
136 [ - + ]: 3420 : if (rx->size) {
137 [ # # ]: 0 : VLOG_ERR_RL(&rl, "connection dropped mid-packet");
138 : 0 : return EPROTO;
139 : : }
140 : 3420 : return EOF;
141 : : } else {
142 : 126042 : return -retval;
143 : : }
144 : : }
145 : :
146 : : static int
147 : 210236 : vconn_stream_recv(struct vconn *vconn, struct ofpbuf **bufferp)
148 : : {
149 : 210236 : struct vconn_stream *s = vconn_stream_cast(vconn);
150 : : const struct ofp_header *oh;
151 : : int rx_len;
152 : :
153 : : /* Allocate new receive buffer if we don't have one. */
154 [ + + ]: 210236 : if (s->rxbuf == NULL) {
155 : 84462 : s->rxbuf = ofpbuf_new(1564);
156 : : }
157 : :
158 : : /* Read ofp_header. */
159 [ + - ]: 210236 : if (s->rxbuf->size < sizeof(struct ofp_header)) {
160 : 210236 : int retval = vconn_stream_recv__(s, sizeof(struct ofp_header));
161 [ + + ]: 210236 : if (retval) {
162 : 129462 : return retval;
163 : : }
164 : : }
165 : :
166 : : /* Read payload. */
167 : 80774 : oh = s->rxbuf->data;
168 : 80774 : rx_len = ntohs(oh->length);
169 [ + + ]: 80774 : if (rx_len < sizeof(struct ofp_header)) {
170 [ + - ]: 3 : VLOG_ERR_RL(&rl, "received too-short ofp_header (%d bytes)", rx_len);
171 : 3 : return EPROTO;
172 [ + + ]: 80771 : } else if (s->rxbuf->size < rx_len) {
173 : 44400 : int retval = vconn_stream_recv__(s, rx_len);
174 [ - + ]: 44400 : if (retval) {
175 : 0 : return retval;
176 : : }
177 : : }
178 : :
179 : 80771 : s->n_packets++;
180 : 80771 : *bufferp = s->rxbuf;
181 : 80771 : s->rxbuf = NULL;
182 : 80771 : return 0;
183 : : }
184 : :
185 : : static void
186 : 6955 : vconn_stream_clear_txbuf(struct vconn_stream *s)
187 : : {
188 : 6955 : ofpbuf_delete(s->txbuf);
189 : 6955 : s->txbuf = NULL;
190 : 6955 : }
191 : :
192 : : static int
193 : 93528 : vconn_stream_send(struct vconn *vconn, struct ofpbuf *buffer)
194 : : {
195 : 93528 : struct vconn_stream *s = vconn_stream_cast(vconn);
196 : : ssize_t retval;
197 : :
198 [ + + ]: 93528 : if (s->txbuf) {
199 : 12654 : return EAGAIN;
200 : : }
201 : :
202 : 80874 : retval = stream_send(s->stream, buffer->data, buffer->size);
203 [ + + ]: 80874 : if (retval == buffer->size) {
204 : 80784 : ofpbuf_delete(buffer);
205 : 80784 : return 0;
206 [ + - ][ + + ]: 90 : } else if (retval >= 0 || retval == -EAGAIN) {
207 : 85 : s->txbuf = buffer;
208 [ - + ]: 85 : if (retval > 0) {
209 : 0 : ofpbuf_pull(buffer, retval);
210 : : }
211 : 85 : return 0;
212 : : } else {
213 : 5 : return -retval;
214 : : }
215 : : }
216 : :
217 : : static void
218 : 125346 : vconn_stream_run(struct vconn *vconn)
219 : : {
220 : 125346 : struct vconn_stream *s = vconn_stream_cast(vconn);
221 : : ssize_t retval;
222 : :
223 : 125346 : stream_run(s->stream);
224 [ + + ]: 125346 : if (!s->txbuf) {
225 : 112688 : return;
226 : : }
227 : :
228 : 12658 : retval = stream_send(s->stream, s->txbuf->data, s->txbuf->size);
229 [ + + ]: 12658 : if (retval < 0) {
230 [ - + ]: 12573 : if (retval != -EAGAIN) {
231 [ # # ]: 0 : VLOG_ERR_RL(&rl, "send: %s", ovs_strerror(-retval));
232 : 0 : vconn_stream_clear_txbuf(s);
233 : 0 : return;
234 : : }
235 [ + - ]: 85 : } else if (retval > 0) {
236 : 85 : ofpbuf_pull(s->txbuf, retval);
237 [ + - ]: 85 : if (!s->txbuf->size) {
238 : 85 : vconn_stream_clear_txbuf(s);
239 : 85 : return;
240 : : }
241 : : }
242 : : }
243 : :
244 : : static void
245 : 124578 : vconn_stream_run_wait(struct vconn *vconn)
246 : : {
247 : 124578 : struct vconn_stream *s = vconn_stream_cast(vconn);
248 : :
249 : 124578 : stream_run_wait(s->stream);
250 [ + + ]: 124578 : if (s->txbuf) {
251 : 12658 : stream_send_wait(s->stream);
252 : : }
253 : 124578 : }
254 : :
255 : : static void
256 : 144192 : vconn_stream_wait(struct vconn *vconn, enum vconn_wait_type wait)
257 : : {
258 : 144192 : struct vconn_stream *s = vconn_stream_cast(vconn);
259 [ + + + - ]: 144192 : switch (wait) {
260 : : case WAIT_CONNECT:
261 : 64 : stream_connect_wait(s->stream);
262 : 64 : break;
263 : :
264 : : case WAIT_SEND:
265 [ + + ]: 19492 : if (!s->txbuf) {
266 : 6838 : stream_send_wait(s->stream);
267 : : } else {
268 : : /* Nothing to do: need to drain txbuf first.
269 : : * vconn_stream_run_wait() will arrange to wake up when there room
270 : : * to send data, so there's no point in calling poll_fd_wait()
271 : : * redundantly here. */
272 : : }
273 : 19492 : break;
274 : :
275 : : case WAIT_RECV:
276 : 124636 : stream_recv_wait(s->stream);
277 : 124636 : break;
278 : :
279 : : default:
280 : 0 : OVS_NOT_REACHED();
281 : : }
282 : 144192 : }
283 : :
284 : : /* Passive stream socket vconn. */
285 : :
286 : : struct pvconn_pstream
287 : : {
288 : : struct pvconn pvconn;
289 : : struct pstream *pstream;
290 : : };
291 : :
292 : : static const struct pvconn_class pstream_pvconn_class;
293 : :
294 : : static struct pvconn_pstream *
295 : 624004 : pvconn_pstream_cast(struct pvconn *pvconn)
296 : : {
297 : 624004 : return CONTAINER_OF(pvconn, struct pvconn_pstream, pvconn);
298 : : }
299 : :
300 : : /* Creates a new pvconn named 'name' that will accept new connections using
301 : : * pstream_accept() and stores a pointer to the pvconn in '*pvconnp'.
302 : : *
303 : : * Returns 0 if successful, otherwise a positive errno value. (The current
304 : : * implementation never fails.) */
305 : : static int
306 : 1499 : pvconn_pstream_listen(const char *name, uint32_t allowed_versions,
307 : : char *suffix OVS_UNUSED, struct pvconn **pvconnp,
308 : : uint8_t dscp)
309 : : {
310 : : struct pvconn_pstream *ps;
311 : : struct pstream *pstream;
312 : : int error;
313 : :
314 : 1499 : error = pstream_open_with_default_port(name, OFP_PORT, &pstream, dscp);
315 [ - + ]: 1499 : if (error) {
316 : 0 : return error;
317 : : }
318 : :
319 : 1499 : ps = xmalloc(sizeof *ps);
320 : 1499 : pvconn_init(&ps->pvconn, &pstream_pvconn_class, name, allowed_versions);
321 : 1499 : ps->pstream = pstream;
322 : 1499 : *pvconnp = &ps->pvconn;
323 : 1499 : return 0;
324 : : }
325 : :
326 : : static void
327 : 1499 : pvconn_pstream_close(struct pvconn *pvconn)
328 : : {
329 : 1499 : struct pvconn_pstream *ps = pvconn_pstream_cast(pvconn);
330 : 1499 : pstream_close(ps->pstream);
331 : 1499 : free(ps);
332 : 1499 : }
333 : :
334 : : static int
335 : 315213 : pvconn_pstream_accept(struct pvconn *pvconn, struct vconn **new_vconnp)
336 : : {
337 : 315213 : struct pvconn_pstream *ps = pvconn_pstream_cast(pvconn);
338 : : struct stream *stream;
339 : : int error;
340 : :
341 : 315213 : error = pstream_accept(ps->pstream, &stream);
342 [ + + ]: 315213 : if (error) {
343 [ - + ]: 311794 : if (error != EAGAIN) {
344 [ # # ]: 0 : VLOG_DBG_RL(&rl, "%s: accept: %s",
345 : : pstream_get_name(ps->pstream), ovs_strerror(error));
346 : : }
347 : 311794 : return error;
348 : : }
349 : :
350 : 3419 : *new_vconnp = vconn_stream_new(stream, 0, pvconn->allowed_versions);
351 : 315213 : return 0;
352 : : }
353 : :
354 : : static void
355 : 307292 : pvconn_pstream_wait(struct pvconn *pvconn)
356 : : {
357 : 307292 : struct pvconn_pstream *ps = pvconn_pstream_cast(pvconn);
358 : 307292 : pstream_wait(ps->pstream);
359 : 307292 : }
360 : :
361 : : /* Stream-based vconns and pvconns. */
362 : :
363 : : #define STREAM_INIT(NAME) \
364 : : { \
365 : : NAME, \
366 : : vconn_stream_open, \
367 : : vconn_stream_close, \
368 : : vconn_stream_connect, \
369 : : vconn_stream_recv, \
370 : : vconn_stream_send, \
371 : : vconn_stream_run, \
372 : : vconn_stream_run_wait, \
373 : : vconn_stream_wait, \
374 : : }
375 : :
376 : : #define PSTREAM_INIT(NAME) \
377 : : { \
378 : : NAME, \
379 : : pvconn_pstream_listen, \
380 : : pvconn_pstream_close, \
381 : : pvconn_pstream_accept, \
382 : : pvconn_pstream_wait \
383 : : }
384 : :
385 : : static const struct vconn_class stream_vconn_class = STREAM_INIT("stream");
386 : : static const struct pvconn_class pstream_pvconn_class = PSTREAM_INIT("pstream");
387 : :
388 : : const struct vconn_class tcp_vconn_class = STREAM_INIT("tcp");
389 : : const struct pvconn_class ptcp_pvconn_class = PSTREAM_INIT("ptcp");
390 : :
391 : : const struct vconn_class unix_vconn_class = STREAM_INIT("unix");
392 : : const struct pvconn_class punix_pvconn_class = PSTREAM_INIT("punix");
393 : :
394 : : #ifdef HAVE_OPENSSL
395 : : const struct vconn_class ssl_vconn_class = STREAM_INIT("ssl");
396 : : const struct pvconn_class pssl_pvconn_class = PSTREAM_INIT("pssl");
397 : : #endif
|