Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 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 "vconn-provider.h"
19 : : #include <errno.h>
20 : : #include <inttypes.h>
21 : : #include <netinet/in.h>
22 : : #include <poll.h>
23 : : #include <stdlib.h>
24 : : #include <string.h>
25 : : #include "coverage.h"
26 : : #include "fatal-signal.h"
27 : : #include "flow.h"
28 : : #include "openflow/nicira-ext.h"
29 : : #include "openflow/openflow.h"
30 : : #include "openvswitch/dynamic-string.h"
31 : : #include "openvswitch/ofp-errors.h"
32 : : #include "openvswitch/ofp-msgs.h"
33 : : #include "openvswitch/ofp-print.h"
34 : : #include "openvswitch/ofp-util.h"
35 : : #include "openvswitch/ofpbuf.h"
36 : : #include "openvswitch/vlog.h"
37 : : #include "packets.h"
38 : : #include "poll-loop.h"
39 : : #include "random.h"
40 : : #include "util.h"
41 : : #include "socket-util.h"
42 : :
43 : 19636 : VLOG_DEFINE_THIS_MODULE(vconn);
44 : :
45 : 133630 : COVERAGE_DEFINE(vconn_open);
46 : 576892 : COVERAGE_DEFINE(vconn_received);
47 : 431386 : COVERAGE_DEFINE(vconn_sent);
48 : :
49 : : /* State of an active vconn.*/
50 : : enum vconn_state {
51 : : /* This is the ordinary progression of states. */
52 : : VCS_CONNECTING, /* Underlying vconn is not connected. */
53 : : VCS_SEND_HELLO, /* Waiting to send OFPT_HELLO message. */
54 : : VCS_RECV_HELLO, /* Waiting to receive OFPT_HELLO message. */
55 : : VCS_CONNECTED, /* Connection established. */
56 : :
57 : : /* These states are entered only when something goes wrong. */
58 : : VCS_SEND_ERROR, /* Sending OFPT_ERROR message. */
59 : : VCS_DISCONNECTED /* Connection failed or connection closed. */
60 : : };
61 : :
62 : : static const struct vconn_class *vconn_classes[] = {
63 : : &tcp_vconn_class,
64 : : &unix_vconn_class,
65 : : #ifdef HAVE_OPENSSL
66 : : &ssl_vconn_class,
67 : : #endif
68 : : };
69 : :
70 : : static const struct pvconn_class *pvconn_classes[] = {
71 : : &ptcp_pvconn_class,
72 : : &punix_pvconn_class,
73 : : #ifdef HAVE_OPENSSL
74 : : &pssl_pvconn_class,
75 : : #endif
76 : : };
77 : :
78 : : /* Rate limit for individual OpenFlow messages going over the vconn, output at
79 : : * DBG level. This is very high because, if these are enabled, it is because
80 : : * we really need to see them. */
81 : : static struct vlog_rate_limit ofmsg_rl = VLOG_RATE_LIMIT_INIT(600, 600);
82 : :
83 : : /* Rate limit for OpenFlow message parse errors. These always indicate a bug
84 : : * in the peer and so there's not much point in showing a lot of them. */
85 : : static struct vlog_rate_limit bad_ofmsg_rl = VLOG_RATE_LIMIT_INIT(1, 5);
86 : :
87 : : static int do_recv(struct vconn *, struct ofpbuf **);
88 : : static int do_send(struct vconn *, struct ofpbuf *);
89 : :
90 : : /* Check the validity of the vconn class structures. */
91 : : static void
92 : 8393 : check_vconn_classes(void)
93 : : {
94 : : #ifndef NDEBUG
95 : : size_t i;
96 : :
97 [ + + ]: 33572 : for (i = 0; i < ARRAY_SIZE(vconn_classes); i++) {
98 : 25179 : const struct vconn_class *class = vconn_classes[i];
99 [ - + ]: 25179 : ovs_assert(class->name != NULL);
100 [ - + ]: 25179 : ovs_assert(class->open != NULL);
101 [ - + ][ # # ]: 25179 : if (class->close || class->recv || class->send
[ # # ]
102 [ # # ][ # # ]: 0 : || class->run || class->run_wait || class->wait) {
[ # # ]
103 [ - + ]: 25179 : ovs_assert(class->close != NULL);
104 [ - + ]: 25179 : ovs_assert(class->recv != NULL);
105 [ - + ]: 25179 : ovs_assert(class->send != NULL);
106 [ - + ]: 25179 : ovs_assert(class->wait != NULL);
107 : : } else {
108 : : /* This class delegates to another one. */
109 : : }
110 : : }
111 : :
112 [ + + ]: 33572 : for (i = 0; i < ARRAY_SIZE(pvconn_classes); i++) {
113 : 25179 : const struct pvconn_class *class = pvconn_classes[i];
114 [ - + ]: 25179 : ovs_assert(class->name != NULL);
115 [ - + ]: 25179 : ovs_assert(class->listen != NULL);
116 [ - + ][ # # ]: 25179 : if (class->close || class->accept || class->wait) {
[ # # ]
117 [ - + ]: 25179 : ovs_assert(class->close != NULL);
118 [ - + ]: 25179 : ovs_assert(class->accept != NULL);
119 [ - + ]: 25179 : ovs_assert(class->wait != NULL);
120 : : } else {
121 : : /* This class delegates to another one. */
122 : : }
123 : : }
124 : : #endif
125 : 8393 : }
126 : :
127 : : /* Prints information on active (if 'active') and passive (if 'passive')
128 : : * connection methods supported by the vconn. If 'bootstrap' is true, also
129 : : * advertises options to bootstrap the CA certificate. */
130 : : void
131 : 0 : vconn_usage(bool active, bool passive, bool bootstrap OVS_UNUSED)
132 : : {
133 : : /* Really this should be implemented via callbacks into the vconn
134 : : * providers, but that seems too heavy-weight to bother with at the
135 : : * moment. */
136 : :
137 : 0 : printf("\n");
138 [ # # ]: 0 : if (active) {
139 : 0 : printf("Active OpenFlow connection methods:\n");
140 : 0 : printf(" tcp:IP[:PORT] "
141 : : "PORT (default: %d) at remote IP\n", OFP_PORT);
142 : : #ifdef HAVE_OPENSSL
143 : 0 : printf(" ssl:IP[:PORT] "
144 : : "SSL PORT (default: %d) at remote IP\n", OFP_PORT);
145 : : #endif
146 : 0 : printf(" unix:FILE Unix domain socket named FILE\n");
147 : : }
148 : :
149 [ # # ]: 0 : if (passive) {
150 : 0 : printf("Passive OpenFlow connection methods:\n");
151 : 0 : printf(" ptcp:[PORT][:IP] "
152 : : "listen to TCP PORT (default: %d) on IP\n",
153 : : OFP_PORT);
154 : : #ifdef HAVE_OPENSSL
155 : 0 : printf(" pssl:[PORT][:IP] "
156 : : "listen for SSL on PORT (default: %d) on IP\n",
157 : : OFP_PORT);
158 : : #endif
159 : 0 : printf(" punix:FILE "
160 : : "listen on Unix domain socket FILE\n");
161 : : }
162 : :
163 : : #ifdef HAVE_OPENSSL
164 : 0 : printf("PKI configuration (required to use SSL):\n"
165 : : " -p, --private-key=FILE file with private key\n"
166 : : " -c, --certificate=FILE file with certificate for private key\n"
167 : : " -C, --ca-cert=FILE file with peer CA certificate\n");
168 [ # # ]: 0 : if (bootstrap) {
169 : 0 : printf(" --bootstrap-ca-cert=FILE file with peer CA certificate "
170 : : "to read or create\n");
171 : : }
172 : : #endif
173 : 0 : }
174 : :
175 : : /* Given 'name', a connection name in the form "TYPE:ARGS", stores the class
176 : : * named "TYPE" into '*classp' and returns 0. Returns EAFNOSUPPORT and stores
177 : : * a null pointer into '*classp' if 'name' is in the wrong form or if no such
178 : : * class exists. */
179 : : static int
180 : 11603 : vconn_lookup_class(const char *name, const struct vconn_class **classp)
181 : : {
182 : : size_t prefix_len;
183 : :
184 : 11603 : prefix_len = strcspn(name, ":");
185 [ + - ]: 11603 : if (name[prefix_len] != '\0') {
186 : : size_t i;
187 : :
188 [ + + ]: 32602 : for (i = 0; i < ARRAY_SIZE(vconn_classes); i++) {
189 : 27899 : const struct vconn_class *class = vconn_classes[i];
190 [ + + ]: 27899 : if (strlen(class->name) == prefix_len
191 [ + + ]: 6908 : && !memcmp(class->name, name, prefix_len)) {
192 : 6900 : *classp = class;
193 : 6900 : return 0;
194 : : }
195 : : }
196 : : }
197 : :
198 : 4703 : *classp = NULL;
199 : 4703 : return EAFNOSUPPORT;
200 : : }
201 : :
202 : : /* Returns 0 if 'name' is a connection name in the form "TYPE:ARGS" and TYPE is
203 : : * a supported connection type, otherwise EAFNOSUPPORT. */
204 : : int
205 : 4709 : vconn_verify_name(const char *name)
206 : : {
207 : : const struct vconn_class *class;
208 : 4709 : return vconn_lookup_class(name, &class);
209 : : }
210 : :
211 : : /* Attempts to connect to an OpenFlow device. 'name' is a connection name in
212 : : * the form "TYPE:ARGS", where TYPE is an active vconn class's name and ARGS
213 : : * are vconn class-specific.
214 : : *
215 : : * The vconn will automatically negotiate an OpenFlow protocol version
216 : : * acceptable to both peers on the connection. The version negotiated will be
217 : : * one of those in the 'allowed_versions' bitmap: version 'x' is allowed if
218 : : * allowed_versions & (1 << x) is nonzero. If 'allowed_versions' is zero, then
219 : : * OFPUTIL_DEFAULT_VERSIONS are allowed.
220 : : *
221 : : * Returns 0 if successful, otherwise a positive errno value. If successful,
222 : : * stores a pointer to the new connection in '*vconnp', otherwise a null
223 : : * pointer. */
224 : : int
225 : 6894 : vconn_open(const char *name, uint32_t allowed_versions, uint8_t dscp,
226 : : struct vconn **vconnp)
227 : : {
228 : : const struct vconn_class *class;
229 : : struct vconn *vconn;
230 : : char *suffix_copy;
231 : : int error;
232 : :
233 : 6894 : COVERAGE_INC(vconn_open);
234 : 6894 : check_vconn_classes();
235 : :
236 [ + + ]: 6894 : if (!allowed_versions) {
237 : 24 : allowed_versions = OFPUTIL_DEFAULT_VERSIONS;
238 : : }
239 : :
240 : : /* Look up the class. */
241 : 6894 : error = vconn_lookup_class(name, &class);
242 [ - + ]: 6894 : if (!class) {
243 : 0 : goto error;
244 : : }
245 : :
246 : : /* Call class's "open" function. */
247 : 6894 : suffix_copy = xstrdup(strchr(name, ':') + 1);
248 : 6894 : error = class->open(name, allowed_versions, suffix_copy, &vconn, dscp);
249 : 6894 : free(suffix_copy);
250 [ + + ]: 6894 : if (error) {
251 : 3392 : goto error;
252 : : }
253 : :
254 : : /* Success. */
255 [ + + ][ - + ]: 3502 : ovs_assert(vconn->state != VCS_CONNECTING || vconn->vclass->connect);
256 : 3502 : *vconnp = vconn;
257 : 3502 : return 0;
258 : :
259 : : error:
260 : 3392 : *vconnp = NULL;
261 : 6894 : return error;
262 : : }
263 : :
264 : : /* Allows 'vconn' to perform maintenance activities, such as flushing output
265 : : * buffers. */
266 : : void
267 : 125346 : vconn_run(struct vconn *vconn)
268 : : {
269 [ + + ][ + + ]: 125346 : if (vconn->state == VCS_CONNECTING ||
270 [ + + ]: 121778 : vconn->state == VCS_SEND_HELLO ||
271 : 121778 : vconn->state == VCS_RECV_HELLO) {
272 : 7094 : vconn_connect(vconn);
273 : : }
274 : :
275 [ + - ]: 125346 : if (vconn->vclass->run) {
276 : 125346 : (vconn->vclass->run)(vconn);
277 : : }
278 : 125346 : }
279 : :
280 : : /* Arranges for the poll loop to wake up when 'vconn' needs to perform
281 : : * maintenance activities. */
282 : : void
283 : 124578 : vconn_run_wait(struct vconn *vconn)
284 : : {
285 [ + + ][ + + ]: 124578 : if (vconn->state == VCS_CONNECTING ||
286 [ + + ]: 121128 : vconn->state == VCS_SEND_HELLO ||
287 : 121128 : vconn->state == VCS_RECV_HELLO) {
288 : 6965 : vconn_connect_wait(vconn);
289 : : }
290 : :
291 [ + - ]: 124578 : if (vconn->vclass->run_wait) {
292 : 124578 : (vconn->vclass->run_wait)(vconn);
293 : : }
294 : 124578 : }
295 : :
296 : : /* Returns 0 if 'vconn' is healthy (connecting or connected), a positive errno
297 : : * value if the connection died abnormally (connection failed or aborted), or
298 : : * EOF if the connection was closed in a normal way. */
299 : : int
300 : 110275 : vconn_get_status(const struct vconn *vconn)
301 : : {
302 [ + + ]: 110275 : return vconn->error == EAGAIN ? 0 : vconn->error;
303 : : }
304 : :
305 : : int
306 : 0 : vconn_open_block(const char *name, uint32_t allowed_versions, uint8_t dscp,
307 : : struct vconn **vconnp)
308 : : {
309 : : struct vconn *vconn;
310 : : int error;
311 : :
312 : 0 : fatal_signal_run();
313 : :
314 : 0 : error = vconn_open(name, allowed_versions, dscp, &vconn);
315 [ # # ]: 0 : if (!error) {
316 : 0 : error = vconn_connect_block(vconn);
317 : : }
318 : :
319 [ # # ]: 0 : if (error) {
320 : 0 : vconn_close(vconn);
321 : 0 : *vconnp = NULL;
322 : : } else {
323 : 0 : *vconnp = vconn;
324 : : }
325 : 0 : return error;
326 : : }
327 : :
328 : : /* Closes 'vconn'. */
329 : : void
330 : 10262 : vconn_close(struct vconn *vconn)
331 : : {
332 [ + + ]: 10262 : if (vconn != NULL) {
333 : 6870 : char *name = vconn->name;
334 : 6870 : (vconn->vclass->close)(vconn);
335 : 6870 : free(name);
336 : : }
337 : 10262 : }
338 : :
339 : : /* Returns the name of 'vconn', that is, the string passed to vconn_open(). */
340 : : const char *
341 : 20707 : vconn_get_name(const struct vconn *vconn)
342 : : {
343 : 20707 : return vconn->name;
344 : : }
345 : :
346 : : /* Returns the allowed_versions of 'vconn', that is,
347 : : * the allowed_versions passed to vconn_open(). */
348 : : uint32_t
349 : 3419 : vconn_get_allowed_versions(const struct vconn *vconn)
350 : : {
351 : 3419 : return vconn->allowed_versions;
352 : : }
353 : :
354 : : /* Sets the allowed_versions of 'vconn', overriding
355 : : * the allowed_versions passed to vconn_open(). */
356 : : void
357 : 0 : vconn_set_allowed_versions(struct vconn *vconn, uint32_t allowed_versions)
358 : : {
359 : 0 : vconn->allowed_versions = allowed_versions;
360 : 0 : }
361 : :
362 : : /* Returns the OpenFlow version negotiated with the peer, or -1 if version
363 : : * negotiation is not yet complete.
364 : : *
365 : : * A vconn that has successfully connected (that is, vconn_connect() or
366 : : * vconn_send() or vconn_recv() has returned 0) always negotiated a version. */
367 : : int
368 : 22834 : vconn_get_version(const struct vconn *vconn)
369 : : {
370 [ + + ]: 22834 : return vconn->version ? vconn->version : -1;
371 : : }
372 : :
373 : : /* By default, a vconn accepts only OpenFlow messages whose version matches the
374 : : * one negotiated for the connection. A message received with a different
375 : : * version is an error that causes the vconn to drop the connection.
376 : : *
377 : : * This functions allows 'vconn' to accept messages with any OpenFlow version.
378 : : * This is useful in the special case where 'vconn' is used as an rconn
379 : : * "monitor" connection (see rconn_add_monitor()), that is, where 'vconn' is
380 : : * used as a target for mirroring OpenFlow messages for debugging and
381 : : * troubleshooting.
382 : : *
383 : : * This function should be called after a successful vconn_open() or
384 : : * pvconn_accept() but before the connection completes, that is, before
385 : : * vconn_connect() returns success. Otherwise, messages that arrive on 'vconn'
386 : : * beforehand with an unexpected version will the vconn to drop the
387 : : * connection. */
388 : : void
389 : 0 : vconn_set_recv_any_version(struct vconn *vconn)
390 : : {
391 : 0 : vconn->recv_any_version = true;
392 : 0 : }
393 : :
394 : : static void
395 : 75 : vcs_connecting(struct vconn *vconn)
396 : : {
397 : 75 : int retval = (vconn->vclass->connect)(vconn);
398 [ - + ]: 75 : ovs_assert(retval != EINPROGRESS);
399 [ + + ]: 75 : if (!retval) {
400 : 6 : vconn->state = VCS_SEND_HELLO;
401 [ + + ]: 69 : } else if (retval != EAGAIN) {
402 : 2 : vconn->state = VCS_DISCONNECTED;
403 : 2 : vconn->error = retval;
404 : : }
405 : 75 : }
406 : :
407 : : static void
408 : 6915 : vcs_send_hello(struct vconn *vconn)
409 : : {
410 : : struct ofpbuf *b;
411 : : int retval;
412 : :
413 : 6915 : b = ofputil_encode_hello(vconn->allowed_versions);
414 : 6915 : retval = do_send(vconn, b);
415 [ + + ]: 6915 : if (!retval) {
416 : 6913 : vconn->state = VCS_RECV_HELLO;
417 : : } else {
418 : 2 : ofpbuf_delete(b);
419 [ + - ]: 2 : if (retval != EAGAIN) {
420 : 2 : vconn->state = VCS_DISCONNECTED;
421 : 2 : vconn->error = retval;
422 : : }
423 : : }
424 : 6915 : }
425 : :
426 : : static char *
427 : 13798 : version_bitmap_to_string(uint32_t bitmap)
428 : : {
429 : : struct ds s;
430 : :
431 : 13798 : ds_init(&s);
432 [ - + ]: 13798 : if (!bitmap) {
433 : 0 : ds_put_cstr(&s, "no versions");
434 [ + + ]: 13798 : } else if (is_pow2(bitmap)) {
435 : 6895 : ds_put_cstr(&s, "version ");
436 : 6895 : ofputil_format_version(&s, leftmost_1bit_idx(bitmap));
437 [ + - ]: 6903 : } else if (is_pow2((bitmap >> 1) + 1)) {
438 : 6903 : ds_put_cstr(&s, "version ");
439 : 6903 : ofputil_format_version(&s, leftmost_1bit_idx(bitmap));
440 : 6903 : ds_put_cstr(&s, " and earlier");
441 : : } else {
442 : 0 : ds_put_cstr(&s, "versions ");
443 : 0 : ofputil_format_version_bitmap(&s, bitmap);
444 : : }
445 : 13798 : return ds_steal_cstr(&s);
446 : : }
447 : :
448 : : static void
449 : 13960 : vcs_recv_hello(struct vconn *vconn)
450 : : {
451 : : struct ofpbuf *b;
452 : : int retval;
453 : :
454 : 13960 : retval = do_recv(vconn, &b);
455 [ + + ]: 13960 : if (!retval) {
456 : : enum ofptype type;
457 : : enum ofperr error;
458 : :
459 : 6905 : error = ofptype_decode(&type, b->data);
460 [ + + ][ + + ]: 6905 : if (!error && type == OFPTYPE_HELLO) {
461 : : char *peer_s, *local_s;
462 : : uint32_t common_versions;
463 : :
464 [ + + ]: 6899 : if (!ofputil_decode_hello(b->data, &vconn->peer_versions)) {
465 : 3 : struct ds msg = DS_EMPTY_INITIALIZER;
466 : 3 : ds_put_format(&msg, "%s: unknown data in hello:\n",
467 : : vconn->name);
468 : 3 : ds_put_hex_dump(&msg, b->data, b->size, 0, true);
469 [ + - ]: 3 : VLOG_WARN_RL(&bad_ofmsg_rl, "%s", ds_cstr(&msg));
470 : 3 : ds_destroy(&msg);
471 : : }
472 : :
473 : 6899 : local_s = version_bitmap_to_string(vconn->allowed_versions);
474 : 6899 : peer_s = version_bitmap_to_string(vconn->peer_versions);
475 : :
476 : 6899 : common_versions = vconn->peer_versions & vconn->allowed_versions;
477 [ - + ]: 6899 : if (!common_versions) {
478 : 0 : vconn->version = leftmost_1bit_idx(vconn->peer_versions);
479 [ # # ]: 0 : VLOG_WARN_RL(&bad_ofmsg_rl,
480 : : "%s: version negotiation failed (we support "
481 : : "%s, peer supports %s)",
482 : : vconn->name, local_s, peer_s);
483 : 0 : vconn->state = VCS_SEND_ERROR;
484 : : } else {
485 : 6899 : vconn->version = leftmost_1bit_idx(common_versions);
486 [ + + ]: 6899 : VLOG_DBG("%s: negotiated OpenFlow version 0x%02x "
487 : : "(we support %s, peer supports %s)", vconn->name,
488 : : vconn->version, local_s, peer_s);
489 : 6899 : vconn->state = VCS_CONNECTED;
490 : : }
491 : :
492 : 6899 : free(local_s);
493 : 6899 : free(peer_s);
494 : :
495 : 6899 : ofpbuf_delete(b);
496 : 6899 : return;
497 : : } else {
498 : 6 : char *s = ofp_to_string(b->data, b->size, 1);
499 [ + - ]: 6 : VLOG_WARN_RL(&bad_ofmsg_rl,
500 : : "%s: received message while expecting hello: %s",
501 : : vconn->name, s);
502 : 6 : free(s);
503 : 6 : retval = EPROTO;
504 : 6 : ofpbuf_delete(b);
505 : : }
506 : : }
507 : :
508 [ + + ]: 7061 : if (retval != EAGAIN) {
509 : 14 : vconn->state = VCS_DISCONNECTED;
510 [ + + ]: 7061 : vconn->error = retval == EOF ? ECONNRESET : retval;
511 : : }
512 : : }
513 : :
514 : : static void
515 : 0 : vcs_send_error(struct vconn *vconn)
516 : : {
517 : : struct ofpbuf *b;
518 : : char s[128];
519 : : int retval;
520 : : char *local_s, *peer_s;
521 : :
522 : 0 : local_s = version_bitmap_to_string(vconn->allowed_versions);
523 : 0 : peer_s = version_bitmap_to_string(vconn->peer_versions);
524 : 0 : snprintf(s, sizeof s, "We support %s, you support %s, no common versions.",
525 : : local_s, peer_s);
526 : 0 : free(peer_s);
527 : 0 : free(local_s);
528 : :
529 : 0 : b = ofperr_encode_hello(OFPERR_OFPHFC_INCOMPATIBLE, vconn->version, s);
530 : 0 : retval = do_send(vconn, b);
531 [ # # ]: 0 : if (retval) {
532 : 0 : ofpbuf_delete(b);
533 : : }
534 [ # # ]: 0 : if (retval != EAGAIN) {
535 : 0 : vconn->state = VCS_DISCONNECTED;
536 [ # # ]: 0 : vconn->error = retval ? retval : EPROTO;
537 : : }
538 : 0 : }
539 : :
540 : : /* Tries to complete the connection on 'vconn'. If 'vconn''s connection is
541 : : * complete, returns 0 if the connection was successful or a positive errno
542 : : * value if it failed. If the connection is still in progress, returns
543 : : * EAGAIN. */
544 : : int
545 : 297027 : vconn_connect(struct vconn *vconn)
546 : : {
547 : : enum vconn_state last_state;
548 : :
549 : : do {
550 : 310863 : last_state = vconn->state;
551 [ + + + + : 310863 : switch (vconn->state) {
- + - ]
552 : : case VCS_CONNECTING:
553 : 75 : vcs_connecting(vconn);
554 : 75 : break;
555 : :
556 : : case VCS_SEND_HELLO:
557 : 6915 : vcs_send_hello(vconn);
558 : 6915 : break;
559 : :
560 : : case VCS_RECV_HELLO:
561 : 13960 : vcs_recv_hello(vconn);
562 : 13960 : break;
563 : :
564 : : case VCS_CONNECTED:
565 : 289883 : return 0;
566 : :
567 : : case VCS_SEND_ERROR:
568 : 0 : vcs_send_error(vconn);
569 : 0 : break;
570 : :
571 : : case VCS_DISCONNECTED:
572 : 30 : return vconn->error;
573 : :
574 : : default:
575 : 0 : OVS_NOT_REACHED();
576 : : }
577 [ + + ]: 20950 : } while (vconn->state != last_state);
578 : :
579 : 7114 : return EAGAIN;
580 : : }
581 : :
582 : : /* Tries to receive an OpenFlow message from 'vconn'. If successful, stores
583 : : * the received message into '*msgp' and returns 0. The caller is responsible
584 : : * for destroying the message with ofpbuf_delete(). On failure, returns a
585 : : * positive errno value and stores a null pointer into '*msgp'. On normal
586 : : * connection close, returns EOF.
587 : : *
588 : : * vconn_recv will not block waiting for a packet to arrive. If no packets
589 : : * have been received, it returns EAGAIN immediately. */
590 : : int
591 : 199204 : vconn_recv(struct vconn *vconn, struct ofpbuf **msgp)
592 : : {
593 : : struct ofpbuf *msg;
594 : : int retval;
595 : :
596 : 199204 : retval = vconn_connect(vconn);
597 [ + + ]: 199204 : if (!retval) {
598 : 196276 : retval = do_recv(vconn, &msg);
599 : : }
600 [ + + ][ + - ]: 199204 : if (!retval && !vconn->recv_any_version) {
601 : 73866 : const struct ofp_header *oh = msg->data;
602 [ + + ]: 73866 : if (oh->version != vconn->version) {
603 : : enum ofptype type;
604 : :
605 [ + - ]: 2 : if (ofptype_decode(&type, msg->data)
606 [ + - ][ + + ]: 2 : || (type != OFPTYPE_HELLO &&
607 [ + - ]: 1 : type != OFPTYPE_ERROR &&
608 [ + - ]: 1 : type != OFPTYPE_ECHO_REQUEST &&
609 : 1 : type != OFPTYPE_ECHO_REPLY)) {
610 : : struct ofpbuf *reply;
611 : :
612 [ + - ]: 1 : VLOG_ERR_RL(&bad_ofmsg_rl, "%s: received OpenFlow version "
613 : : "0x%02"PRIx8" != expected %02x",
614 : : vconn->name, oh->version, vconn->version);
615 : :
616 : : /* Send a "bad version" reply, if we can. */
617 : 1 : reply = ofperr_encode_reply(OFPERR_OFPBRC_BAD_VERSION, oh);
618 : 1 : retval = vconn_send(vconn, reply);
619 [ - + ]: 1 : if (retval) {
620 [ # # ]: 0 : VLOG_INFO_RL(&bad_ofmsg_rl,
621 : : "%s: failed to queue error reply (%s)",
622 : : vconn->name, ovs_strerror(retval));
623 : 0 : ofpbuf_delete(reply);
624 : : }
625 : :
626 : : /* Suppress the received message, as if it had not arrived. */
627 : 1 : retval = EAGAIN;
628 : 2 : ofpbuf_delete(msg);
629 : : }
630 : : }
631 : : }
632 : :
633 [ + + ]: 199204 : *msgp = retval ? NULL : msg;
634 : 199204 : return retval;
635 : : }
636 : :
637 : : static int
638 : 210236 : do_recv(struct vconn *vconn, struct ofpbuf **msgp)
639 : : {
640 : 210236 : int retval = (vconn->vclass->recv)(vconn, msgp);
641 [ + + ]: 210236 : if (!retval) {
642 : 80771 : COVERAGE_INC(vconn_received);
643 [ + + ]: 80771 : if (VLOG_IS_DBG_ENABLED()) {
644 : 55927 : char *s = ofp_to_string((*msgp)->data, (*msgp)->size, 1);
645 [ + - ]: 55927 : VLOG_DBG_RL(&ofmsg_rl, "%s: received: %s", vconn->name, s);
646 : 55927 : free(s);
647 : : }
648 : : }
649 : 210236 : return retval;
650 : : }
651 : :
652 : : /* Tries to queue 'msg' for transmission on 'vconn'. If successful, returns 0,
653 : : * in which case ownership of 'msg' is transferred to the vconn. Success does
654 : : * not guarantee that 'msg' has been or ever will be delivered to the peer,
655 : : * only that it has been queued for transmission.
656 : : *
657 : : * Returns a positive errno value on failure, in which case the caller
658 : : * retains ownership of 'msg'.
659 : : *
660 : : * vconn_send will not block. If 'msg' cannot be immediately accepted for
661 : : * transmission, it returns EAGAIN immediately. */
662 : : int
663 : 86613 : vconn_send(struct vconn *vconn, struct ofpbuf *msg)
664 : : {
665 : 86613 : int retval = vconn_connect(vconn);
666 [ + - ]: 86613 : if (!retval) {
667 : 86613 : retval = do_send(vconn, msg);
668 : : }
669 : 86613 : return retval;
670 : : }
671 : :
672 : : static int
673 : 93528 : do_send(struct vconn *vconn, struct ofpbuf *msg)
674 : : {
675 : : int retval;
676 : :
677 [ - + ]: 93528 : ovs_assert(msg->size >= sizeof(struct ofp_header));
678 : :
679 : 93528 : ofpmsg_update_length(msg);
680 [ + + ]: 93528 : if (!VLOG_IS_DBG_ENABLED()) {
681 : 56520 : COVERAGE_INC(vconn_sent);
682 : 56520 : retval = (vconn->vclass->send)(vconn, msg);
683 : : } else {
684 : 37008 : char *s = ofp_to_string(msg->data, msg->size, 1);
685 : 37008 : retval = (vconn->vclass->send)(vconn, msg);
686 [ + + ]: 37008 : if (retval != EAGAIN) {
687 [ + - ]: 24447 : VLOG_DBG_RL(&ofmsg_rl, "%s: sent (%s): %s",
688 : : vconn->name, ovs_strerror(retval), s);
689 : : }
690 : 37008 : free(s);
691 : : }
692 : 93528 : return retval;
693 : : }
694 : :
695 : : /* Same as vconn_connect(), except that it waits until the connection on
696 : : * 'vconn' completes or fails. Thus, it will never return EAGAIN. */
697 : : int
698 : 3391 : vconn_connect_block(struct vconn *vconn)
699 : : {
700 : : int error;
701 : :
702 [ + + ]: 3875 : while ((error = vconn_connect(vconn)) == EAGAIN) {
703 : 484 : vconn_run(vconn);
704 : 484 : vconn_run_wait(vconn);
705 : 484 : vconn_connect_wait(vconn);
706 : 484 : poll_block();
707 : : }
708 [ - + ]: 3391 : ovs_assert(error != EINPROGRESS);
709 : :
710 : 3391 : return error;
711 : : }
712 : :
713 : : /* Same as vconn_send, except that it waits until 'msg' can be transmitted. */
714 : : int
715 : 29493 : vconn_send_block(struct vconn *vconn, struct ofpbuf *msg)
716 : : {
717 : : int retval;
718 : :
719 : 29493 : fatal_signal_run();
720 : :
721 [ - + ]: 29493 : while ((retval = vconn_send(vconn, msg)) == EAGAIN) {
722 : 0 : vconn_run(vconn);
723 : 0 : vconn_run_wait(vconn);
724 : 0 : vconn_send_wait(vconn);
725 : 0 : poll_block();
726 : : }
727 : 29493 : return retval;
728 : : }
729 : :
730 : : /* Same as vconn_recv, except that it waits until a message is received. */
731 : : int
732 : 14879 : vconn_recv_block(struct vconn *vconn, struct ofpbuf **msgp)
733 : : {
734 : : int retval;
735 : :
736 : 14879 : fatal_signal_run();
737 : :
738 [ + + ]: 27590 : while ((retval = vconn_recv(vconn, msgp)) == EAGAIN) {
739 : 12711 : vconn_run(vconn);
740 : 12711 : vconn_run_wait(vconn);
741 : 12711 : vconn_recv_wait(vconn);
742 : 12711 : poll_block();
743 : : }
744 : 14879 : return retval;
745 : : }
746 : :
747 : : static void
748 : 13 : vconn_add_bundle_error(const struct ofp_header *oh, struct ovs_list *errors)
749 : : {
750 [ + - ]: 13 : if (errors) {
751 : 13 : struct vconn_bundle_error *err = xmalloc(sizeof *err);
752 : 13 : size_t len = ntohs(oh->length);
753 : :
754 : 13 : memcpy(err->ofp_msg_data, oh, MIN(len, sizeof err->ofp_msg_data));
755 : 13 : ovs_list_push_back(errors, &err->list_node);
756 : : }
757 : 13 : }
758 : :
759 : : static int
760 : 676 : vconn_recv_xid__(struct vconn *vconn, ovs_be32 xid, struct ofpbuf **replyp,
761 : : struct ovs_list *errors)
762 : : {
763 : : for (;;) {
764 : : ovs_be32 recv_xid;
765 : : struct ofpbuf *reply;
766 : : const struct ofp_header *oh;
767 : : enum ofptype type;
768 : : int error;
769 : :
770 : 682 : error = vconn_recv_block(vconn, &reply);
771 [ - + ]: 682 : if (error) {
772 : 0 : *replyp = NULL;
773 : 676 : return error;
774 : : }
775 : 682 : oh = reply->data;
776 : 682 : recv_xid = oh->xid;
777 [ + + ]: 682 : if (xid == recv_xid) {
778 : 676 : *replyp = reply;
779 : 676 : return 0;
780 : : }
781 : :
782 : 6 : error = ofptype_decode(&type, oh);
783 [ + - ][ + - ]: 6 : if (!error && type == OFPTYPE_ERROR) {
784 : 6 : vconn_add_bundle_error(oh, errors);
785 : : } else {
786 [ # # ]: 0 : VLOG_DBG_RL(&bad_ofmsg_rl, "%s: received reply with xid %08"PRIx32
787 : : " != expected %08"PRIx32,
788 : : vconn->name, ntohl(recv_xid), ntohl(xid));
789 : : }
790 : 6 : ofpbuf_delete(reply);
791 : 6 : }
792 : : }
793 : :
794 : : /* Waits until a message with a transaction ID matching 'xid' is received on
795 : : * 'vconn'. Returns 0 if successful, in which case the reply is stored in
796 : : * '*replyp' for the caller to examine and free. Otherwise returns a positive
797 : : * errno value, or EOF, and sets '*replyp' to null.
798 : : *
799 : : * 'request' is always destroyed, regardless of the return value. */
800 : : int
801 : 0 : vconn_recv_xid(struct vconn *vconn, ovs_be32 xid, struct ofpbuf **replyp)
802 : : {
803 : 0 : return vconn_recv_xid__(vconn, xid, replyp, NULL);
804 : : }
805 : :
806 : : static int
807 : 557 : vconn_transact__(struct vconn *vconn, struct ofpbuf *request,
808 : : struct ofpbuf **replyp, struct ovs_list *errors)
809 : : {
810 : 557 : ovs_be32 send_xid = ((struct ofp_header *) request->data)->xid;
811 : : int error;
812 : :
813 : 557 : *replyp = NULL;
814 : 557 : error = vconn_send_block(vconn, request);
815 [ - + ]: 557 : if (error) {
816 : 0 : ofpbuf_delete(request);
817 : : }
818 [ + - ]: 557 : return error ? error : vconn_recv_xid__(vconn, send_xid, replyp, errors);
819 : : }
820 : :
821 : : /* Sends 'request' to 'vconn' and blocks until it receives a reply with a
822 : : * matching transaction ID. Returns 0 if successful, in which case the reply
823 : : * is stored in '*replyp' for the caller to examine and free. Otherwise
824 : : * returns a positive errno value, or EOF, and sets '*replyp' to null.
825 : : *
826 : : * 'request' should be an OpenFlow request that requires a reply. Otherwise,
827 : : * if there is no reply, this function can end up blocking forever (or until
828 : : * the peer drops the connection).
829 : : *
830 : : * 'request' is always destroyed, regardless of the return value. */
831 : : int
832 : 319 : vconn_transact(struct vconn *vconn, struct ofpbuf *request,
833 : : struct ofpbuf **replyp)
834 : : {
835 : 319 : return vconn_transact__(vconn, request, replyp, NULL);
836 : : }
837 : :
838 : : static int
839 : 13662 : vconn_send_barrier(struct vconn *vconn, ovs_be32 *barrier_xid)
840 : : {
841 : : struct ofpbuf *barrier;
842 : : int error;
843 : :
844 : : /* Send barrier. */
845 : 13662 : barrier = ofputil_encode_barrier_request(vconn_get_version(vconn));
846 : 13662 : *barrier_xid = ((struct ofp_header *) barrier->data)->xid;
847 : 13662 : error = vconn_send_block(vconn, barrier);
848 [ - + ]: 13662 : if (error) {
849 : 0 : ofpbuf_delete(barrier);
850 : : }
851 : 13662 : return error;
852 : : }
853 : :
854 : : /* Sends 'request' followed by a barrier request to 'vconn', then blocks until
855 : : * it receives a reply to the barrier. If successful, stores the reply to
856 : : * 'request' in '*replyp', if one was received, and otherwise NULL, then
857 : : * returns 0. Otherwise returns a positive errno value, or EOF, and sets
858 : : * '*replyp' to null.
859 : : *
860 : : * This function is useful for sending an OpenFlow request that doesn't
861 : : * ordinarily include a reply but might report an error in special
862 : : * circumstances.
863 : : *
864 : : * 'request' is always destroyed, regardless of the return value. */
865 : : int
866 : 13543 : vconn_transact_noreply(struct vconn *vconn, struct ofpbuf *request,
867 : : struct ofpbuf **replyp)
868 : : {
869 : : ovs_be32 request_xid;
870 : : ovs_be32 barrier_xid;
871 : : int error;
872 : :
873 : 13543 : *replyp = NULL;
874 : :
875 : : /* Send request. */
876 : 13543 : request_xid = ((struct ofp_header *) request->data)->xid;
877 : 13543 : error = vconn_send_block(vconn, request);
878 [ - + ]: 13543 : if (error) {
879 : 0 : ofpbuf_delete(request);
880 : 0 : return error;
881 : : }
882 : :
883 : : /* Send barrier. */
884 : 13543 : error = vconn_send_barrier(vconn, &barrier_xid);
885 [ - + ]: 13543 : if (error) {
886 : 0 : return error;
887 : : }
888 : :
889 : : for (;;) {
890 : : struct ofpbuf *msg;
891 : : ovs_be32 msg_xid;
892 : : int error;
893 : :
894 : 13556 : error = vconn_recv_block(vconn, &msg);
895 [ - + ]: 13556 : if (error) {
896 : 0 : ofpbuf_delete(*replyp);
897 : 0 : *replyp = NULL;
898 : 13543 : return error;
899 : : }
900 : :
901 : 13556 : msg_xid = ((struct ofp_header *) msg->data)->xid;
902 [ + + ]: 13556 : if (msg_xid == request_xid) {
903 [ - + ]: 13 : if (*replyp) {
904 [ # # ]: 0 : VLOG_WARN_RL(&bad_ofmsg_rl, "%s: duplicate replies with "
905 : : "xid %08"PRIx32, vconn->name, ntohl(msg_xid));
906 : 0 : ofpbuf_delete(*replyp);
907 : : }
908 : 13 : *replyp = msg;
909 : : } else {
910 : 13543 : ofpbuf_delete(msg);
911 [ + - ]: 13543 : if (msg_xid == barrier_xid) {
912 : 13543 : return 0;
913 : : } else {
914 [ # # ]: 0 : VLOG_DBG_RL(&bad_ofmsg_rl, "%s: reply with xid %08"PRIx32
915 : : " != expected %08"PRIx32" or %08"PRIx32,
916 : : vconn->name, ntohl(msg_xid),
917 : : ntohl(request_xid), ntohl(barrier_xid));
918 : : }
919 : : }
920 : 13 : }
921 : : }
922 : :
923 : : /* vconn_transact_noreply() for a list of "struct ofpbuf"s, sent one by one.
924 : : * All of the requests on 'requests' are always destroyed, regardless of the
925 : : * return value. */
926 : : int
927 : 13028 : vconn_transact_multiple_noreply(struct vconn *vconn, struct ovs_list *requests,
928 : : struct ofpbuf **replyp)
929 : : {
930 : : struct ofpbuf *request;
931 : :
932 [ + + ]: 26058 : LIST_FOR_EACH_POP (request, list_node, requests) {
933 : : int error;
934 : :
935 : 13043 : error = vconn_transact_noreply(vconn, request, replyp);
936 [ + - ][ + + ]: 13043 : if (error || *replyp) {
937 : 13 : ofpbuf_list_delete(requests);
938 : 13 : return error;
939 : : }
940 : : }
941 : :
942 : 13015 : *replyp = NULL;
943 : 13015 : return 0;
944 : : }
945 : :
946 : : static enum ofperr
947 : 238 : vconn_bundle_reply_validate(struct ofpbuf *reply,
948 : : struct ofputil_bundle_ctrl_msg *request,
949 : : struct ovs_list *errors)
950 : : {
951 : : const struct ofp_header *oh;
952 : : enum ofptype type;
953 : : enum ofperr error;
954 : : struct ofputil_bundle_ctrl_msg rbc;
955 : :
956 : 238 : oh = reply->data;
957 : 238 : error = ofptype_decode(&type, oh);
958 [ - + ]: 238 : if (error) {
959 : 0 : return error;
960 : : }
961 : :
962 [ + + ]: 238 : if (type == OFPTYPE_ERROR) {
963 : 5 : vconn_add_bundle_error(oh, errors);
964 : 5 : return ofperr_decode_msg(oh, NULL);
965 : : }
966 [ - + ]: 233 : if (type != OFPTYPE_BUNDLE_CONTROL) {
967 : 0 : return OFPERR_OFPBRC_BAD_TYPE;
968 : : }
969 : :
970 : 233 : error = ofputil_decode_bundle_ctrl(oh, &rbc);
971 [ - + ]: 233 : if (error) {
972 : 0 : return error;
973 : : }
974 : :
975 [ - + ]: 233 : if (rbc.bundle_id != request->bundle_id) {
976 : 0 : return OFPERR_OFPBFC_BAD_ID;
977 : : }
978 : :
979 [ - + ]: 233 : if (rbc.type != request->type + 1) {
980 : 0 : return OFPERR_OFPBFC_BAD_TYPE;
981 : : }
982 : :
983 : 238 : return 0;
984 : : }
985 : :
986 : : /* Send bundle control message 'bc' of 'type' via 'vconn', and wait for either
987 : : * an error or the corresponding bundle control message response.
988 : : *
989 : : * 'errors' is a list to which any OpenFlow errors relating to bundle
990 : : * processing are appended. Caller is responsible for releasing the memory of
991 : : * each node in the list on return.
992 : : *
993 : : * Returns errno value, or 0 when successful. */
994 : : static int
995 : 238 : vconn_bundle_control_transact(struct vconn *vconn,
996 : : struct ofputil_bundle_ctrl_msg *bc,
997 : : uint16_t type, struct ovs_list *errors)
998 : : {
999 : : struct ofpbuf *request, *reply;
1000 : : int error;
1001 : : enum ofperr ofperr;
1002 : :
1003 : 238 : bc->type = type;
1004 : 238 : request = ofputil_encode_bundle_ctrl_request(vconn->version, bc);
1005 : 238 : ofpmsg_update_length(request);
1006 : 238 : error = vconn_transact__(vconn, request, &reply, errors);
1007 [ - + ]: 238 : if (error) {
1008 : 0 : return error;
1009 : : }
1010 : :
1011 : 238 : ofperr = vconn_bundle_reply_validate(reply, bc, errors);
1012 : 238 : ofpbuf_delete(reply);
1013 : :
1014 [ + + ]: 238 : return ofperr ? EPROTO : 0;
1015 : : }
1016 : :
1017 : : /* Checks if error responses can be received on 'vconn'. */
1018 : : static void
1019 : 735 : vconn_recv_error(struct vconn *vconn, struct ovs_list *errors)
1020 : : {
1021 : : int error;
1022 : :
1023 : : do {
1024 : : struct ofpbuf *reply;
1025 : :
1026 : 737 : error = vconn_recv(vconn, &reply);
1027 [ + + ]: 737 : if (!error) {
1028 : : const struct ofp_header *oh;
1029 : : enum ofptype type;
1030 : : enum ofperr ofperr;
1031 : :
1032 : 2 : oh = reply->data;
1033 : 2 : ofperr = ofptype_decode(&type, oh);
1034 [ + - ][ + - ]: 2 : if (!ofperr && type == OFPTYPE_ERROR) {
1035 : 2 : vconn_add_bundle_error(oh, errors);
1036 : : } else {
1037 [ # # ]: 0 : VLOG_DBG_RL(&bad_ofmsg_rl,
1038 : : "%s: received unexpected reply with xid %08"PRIx32,
1039 : : vconn->name, ntohl(oh->xid));
1040 : : }
1041 : 2 : ofpbuf_delete(reply);
1042 : : }
1043 [ + + ]: 737 : } while (!error);
1044 : 735 : }
1045 : :
1046 : : /* Sends a barrier and waits for the barrier response and stores any errors
1047 : : * that are received before the barrier response. */
1048 : : static int
1049 : 119 : vconn_bundle_barrier_transact(struct vconn *vconn, struct ovs_list *errors)
1050 : : {
1051 : : struct ofpbuf *reply;
1052 : : ovs_be32 barrier_xid;
1053 : : int error;
1054 : :
1055 : 119 : error = vconn_send_barrier(vconn, &barrier_xid);
1056 [ - + ]: 119 : if (error) {
1057 : 0 : return error;
1058 : : }
1059 : :
1060 : 119 : error = vconn_recv_xid__(vconn, barrier_xid, &reply, errors);
1061 [ - + ]: 119 : if (error) {
1062 : 0 : return error;
1063 : : }
1064 : 119 : ofpbuf_delete(reply);
1065 : 119 : return 0;
1066 : : }
1067 : :
1068 : : static int
1069 : 735 : vconn_bundle_add_msg(struct vconn *vconn, struct ofputil_bundle_ctrl_msg *bc,
1070 : : struct ofpbuf *msg,
1071 : : struct ovs_list *errors)
1072 : : {
1073 : : struct ofputil_bundle_add_msg bam;
1074 : : struct ofpbuf *request;
1075 : : int error;
1076 : :
1077 : 735 : ofpmsg_update_length(msg);
1078 : :
1079 : 735 : bam.bundle_id = bc->bundle_id;
1080 : 735 : bam.flags = bc->flags;
1081 : 735 : bam.msg = msg->data;
1082 : :
1083 : 735 : request = ofputil_encode_bundle_add(vconn->version, &bam);
1084 : :
1085 : 735 : error = vconn_send_block(vconn, request);
1086 [ + - ]: 735 : if (!error) {
1087 : : /* Check for an error return, so that the socket buffer does not become
1088 : : * full of errors. */
1089 : 735 : vconn_recv_error(vconn, errors);
1090 : : }
1091 : 735 : return error;
1092 : : }
1093 : :
1094 : : int
1095 : 119 : vconn_bundle_transact(struct vconn *vconn, struct ovs_list *requests,
1096 : : uint16_t flags, struct ovs_list *errors)
1097 : : {
1098 : : struct ofputil_bundle_ctrl_msg bc;
1099 : : struct ofpbuf *request;
1100 : : int error;
1101 : :
1102 : 119 : ovs_list_init(errors);
1103 : :
1104 : 119 : memset(&bc, 0, sizeof bc);
1105 : 119 : bc.flags = flags;
1106 : 119 : error = vconn_bundle_control_transact(vconn, &bc, OFPBCT_OPEN_REQUEST,
1107 : : errors);
1108 [ - + ]: 119 : if (error) {
1109 : 0 : return error;
1110 : : }
1111 : :
1112 [ + + ]: 854 : LIST_FOR_EACH (request, list_node, requests) {
1113 : 735 : error = vconn_bundle_add_msg(vconn, &bc, request, errors);
1114 [ - + ]: 735 : if (error) {
1115 : 0 : break;
1116 : : }
1117 : : }
1118 : :
1119 [ + - ]: 119 : if (!error) {
1120 : : /* A failing message does not invalidate the bundle, but the message is
1121 : : * simply not added to the bundle. Since we do not want to commit if
1122 : : * any of the messages failed, we need to explicitly sync with barrier
1123 : : * before we issue the commit message. */
1124 : 119 : error = vconn_bundle_barrier_transact(vconn, errors);
1125 : : }
1126 [ + - ][ + + ]: 119 : if (!error && !ovs_list_is_empty(errors)) {
1127 : 3 : error = EPROTO;
1128 : : }
1129 : :
1130 : : /* Commit only if no errors are received. */
1131 [ + + ]: 119 : if (!error) {
1132 : 116 : error = vconn_bundle_control_transact(vconn, &bc,
1133 : : OFPBCT_COMMIT_REQUEST,
1134 : : errors);
1135 : : } else {
1136 : 3 : vconn_bundle_control_transact(vconn, &bc, OFPBCT_DISCARD_REQUEST,
1137 : : errors);
1138 : : }
1139 : 119 : return error;
1140 : : }
1141 : :
1142 : : void
1143 : 144192 : vconn_wait(struct vconn *vconn, enum vconn_wait_type wait)
1144 : : {
1145 [ + + ][ + + ]: 144192 : ovs_assert(wait == WAIT_CONNECT || wait == WAIT_RECV || wait == WAIT_SEND);
[ + + ][ - + ]
1146 : :
1147 [ + + + + : 144192 : switch (vconn->state) {
- - ]
1148 : : case VCS_CONNECTING:
1149 : 62 : wait = WAIT_CONNECT;
1150 : 62 : break;
1151 : :
1152 : : case VCS_SEND_HELLO:
1153 : : case VCS_SEND_ERROR:
1154 : 6838 : wait = WAIT_SEND;
1155 : 6838 : break;
1156 : :
1157 : : case VCS_RECV_HELLO:
1158 : 7030 : wait = WAIT_RECV;
1159 : 7030 : break;
1160 : :
1161 : : case VCS_CONNECTED:
1162 : 130262 : break;
1163 : :
1164 : : case VCS_DISCONNECTED:
1165 : 0 : poll_immediate_wake();
1166 : 0 : return;
1167 : : }
1168 : 144192 : (vconn->vclass->wait)(vconn, wait);
1169 : : }
1170 : :
1171 : : void
1172 : 7456 : vconn_connect_wait(struct vconn *vconn)
1173 : : {
1174 : 7456 : vconn_wait(vconn, WAIT_CONNECT);
1175 : 7456 : }
1176 : :
1177 : : void
1178 : 14536 : vconn_recv_wait(struct vconn *vconn)
1179 : : {
1180 : 14536 : vconn_wait(vconn, WAIT_RECV);
1181 : 14536 : }
1182 : :
1183 : : void
1184 : 0 : vconn_send_wait(struct vconn *vconn)
1185 : : {
1186 : 0 : vconn_wait(vconn, WAIT_SEND);
1187 : 0 : }
1188 : :
1189 : : /* Given 'name', a connection name in the form "TYPE:ARGS", stores the class
1190 : : * named "TYPE" into '*classp' and returns 0. Returns EAFNOSUPPORT and stores
1191 : : * a null pointer into '*classp' if 'name' is in the wrong form or if no such
1192 : : * class exists. */
1193 : : static int
1194 : 6202 : pvconn_lookup_class(const char *name, const struct pvconn_class **classp)
1195 : : {
1196 : : size_t prefix_len;
1197 : :
1198 : 6202 : prefix_len = strcspn(name, ":");
1199 [ + - ]: 6202 : if (name[prefix_len] != '\0') {
1200 : : size_t i;
1201 : :
1202 [ + - ]: 12404 : for (i = 0; i < ARRAY_SIZE(pvconn_classes); i++) {
1203 : 12404 : const struct pvconn_class *class = pvconn_classes[i];
1204 [ + + ]: 12404 : if (strlen(class->name) == prefix_len
1205 [ + - ]: 6202 : && !memcmp(class->name, name, prefix_len)) {
1206 : 6202 : *classp = class;
1207 : 6202 : return 0;
1208 : : }
1209 : : }
1210 : : }
1211 : :
1212 : 0 : *classp = NULL;
1213 : 0 : return EAFNOSUPPORT;
1214 : : }
1215 : :
1216 : : /* Returns 0 if 'name' is a connection name in the form "TYPE:ARGS" and TYPE is
1217 : : * a supported connection type, otherwise EAFNOSUPPORT. */
1218 : : int
1219 : 4703 : pvconn_verify_name(const char *name)
1220 : : {
1221 : : const struct pvconn_class *class;
1222 : 4703 : return pvconn_lookup_class(name, &class);
1223 : : }
1224 : :
1225 : : /* Attempts to start listening for OpenFlow connections. 'name' is a
1226 : : * connection name in the form "TYPE:ARGS", where TYPE is an passive vconn
1227 : : * class's name and ARGS are vconn class-specific.
1228 : : *
1229 : : * vconns accepted by the pvconn will automatically negotiate an OpenFlow
1230 : : * protocol version acceptable to both peers on the connection. The version
1231 : : * negotiated will be one of those in the 'allowed_versions' bitmap: version
1232 : : * 'x' is allowed if allowed_versions & (1 << x) is nonzero. If
1233 : : * 'allowed_versions' is zero, then OFPUTIL_DEFAULT_VERSIONS are allowed.
1234 : : *
1235 : : * Returns 0 if successful, otherwise a positive errno value. If successful,
1236 : : * stores a pointer to the new connection in '*pvconnp', otherwise a null
1237 : : * pointer. */
1238 : : int
1239 : 1499 : pvconn_open(const char *name, uint32_t allowed_versions, uint8_t dscp,
1240 : : struct pvconn **pvconnp)
1241 : : {
1242 : : const struct pvconn_class *class;
1243 : : struct pvconn *pvconn;
1244 : : char *suffix_copy;
1245 : : int error;
1246 : :
1247 : 1499 : check_vconn_classes();
1248 : :
1249 [ + + ]: 1499 : if (!allowed_versions) {
1250 : 937 : allowed_versions = OFPUTIL_DEFAULT_VERSIONS;
1251 : : }
1252 : :
1253 : : /* Look up the class. */
1254 : 1499 : error = pvconn_lookup_class(name, &class);
1255 [ - + ]: 1499 : if (!class) {
1256 : 0 : goto error;
1257 : : }
1258 : :
1259 : : /* Call class's "open" function. */
1260 : 1499 : suffix_copy = xstrdup(strchr(name, ':') + 1);
1261 : 1499 : error = class->listen(name, allowed_versions, suffix_copy, &pvconn, dscp);
1262 : 1499 : free(suffix_copy);
1263 [ - + ]: 1499 : if (error) {
1264 : 0 : goto error;
1265 : : }
1266 : :
1267 : : /* Success. */
1268 : 1499 : *pvconnp = pvconn;
1269 : 1499 : return 0;
1270 : :
1271 : : error:
1272 : 0 : *pvconnp = NULL;
1273 : 1499 : return error;
1274 : : }
1275 : :
1276 : : /* Returns the name that was used to open 'pvconn'. The caller must not
1277 : : * modify or free the name. */
1278 : : const char *
1279 : 8653 : pvconn_get_name(const struct pvconn *pvconn)
1280 : : {
1281 : 8653 : return pvconn->name;
1282 : : }
1283 : :
1284 : : /* Closes 'pvconn'. */
1285 : : void
1286 : 1499 : pvconn_close(struct pvconn *pvconn)
1287 : : {
1288 [ + - ]: 1499 : if (pvconn != NULL) {
1289 : 1499 : char *name = pvconn->name;
1290 : 1499 : (pvconn->pvclass->close)(pvconn);
1291 : 1499 : free(name);
1292 : : }
1293 : 1499 : }
1294 : :
1295 : : /* Tries to accept a new connection on 'pvconn'. If successful, stores the new
1296 : : * connection in '*new_vconn' and returns 0. Otherwise, returns a positive
1297 : : * errno value.
1298 : : *
1299 : : * The new vconn will automatically negotiate an OpenFlow protocol version
1300 : : * acceptable to both peers on the connection. The version negotiated will be
1301 : : * no lower than 'min_version' and no higher than 'max_version'.
1302 : : *
1303 : : * pvconn_accept() will not block waiting for a connection. If no connection
1304 : : * is ready to be accepted, it returns EAGAIN immediately. */
1305 : : int
1306 : 315213 : pvconn_accept(struct pvconn *pvconn, struct vconn **new_vconn)
1307 : : {
1308 : 315213 : int retval = (pvconn->pvclass->accept)(pvconn, new_vconn);
1309 [ + + ]: 315213 : if (retval) {
1310 : 311794 : *new_vconn = NULL;
1311 : : } else {
1312 [ - + ][ # # ]: 3419 : ovs_assert((*new_vconn)->state != VCS_CONNECTING
1313 : : || (*new_vconn)->vclass->connect);
1314 : : }
1315 : 315213 : return retval;
1316 : : }
1317 : :
1318 : : void
1319 : 307292 : pvconn_wait(struct pvconn *pvconn)
1320 : : {
1321 : 307292 : (pvconn->pvclass->wait)(pvconn);
1322 : 307292 : }
1323 : :
1324 : : /* Initializes 'vconn' as a new vconn named 'name', implemented via 'class'.
1325 : : * The initial connection status, supplied as 'connect_status', is interpreted
1326 : : * as follows:
1327 : : *
1328 : : * - 0: 'vconn' is connected. Its 'send' and 'recv' functions may be
1329 : : * called in the normal fashion.
1330 : : *
1331 : : * - EAGAIN: 'vconn' is trying to complete a connection. Its 'connect'
1332 : : * function should be called to complete the connection.
1333 : : *
1334 : : * - Other positive errno values indicate that the connection failed with
1335 : : * the specified error.
1336 : : *
1337 : : * After calling this function, vconn_close() must be used to destroy 'vconn',
1338 : : * otherwise resources will be leaked.
1339 : : *
1340 : : * The caller retains ownership of 'name'. */
1341 : : void
1342 : 6921 : vconn_init(struct vconn *vconn, const struct vconn_class *class,
1343 : : int connect_status, const char *name, uint32_t allowed_versions)
1344 : : {
1345 : 6921 : memset(vconn, 0, sizeof *vconn);
1346 : 6921 : vconn->vclass = class;
1347 : 6921 : vconn->state = (connect_status == EAGAIN ? VCS_CONNECTING
1348 [ + + ]: 13830 : : !connect_status ? VCS_SEND_HELLO
1349 [ + - ]: 6909 : : VCS_DISCONNECTED);
1350 : 6921 : vconn->error = connect_status;
1351 : 6921 : vconn->allowed_versions = allowed_versions;
1352 : 6921 : vconn->name = xstrdup(name);
1353 [ + + ][ - + ]: 6921 : ovs_assert(vconn->state != VCS_CONNECTING || class->connect);
1354 : 6921 : }
1355 : :
1356 : : void
1357 : 1499 : pvconn_init(struct pvconn *pvconn, const struct pvconn_class *class,
1358 : : const char *name, uint32_t allowed_versions)
1359 : : {
1360 : 1499 : pvconn->pvclass = class;
1361 : 1499 : pvconn->name = xstrdup(name);
1362 : 1499 : pvconn->allowed_versions = allowed_versions;
1363 : 1499 : }
|