/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "poll-loop.h"
#include "random.h"
#include "util.h"
-#include "vlog.h"
+#include "openvswitch/vlog.h"
#include "socket-util.h"
VLOG_DEFINE_THIS_MODULE(vconn);
if (active) {
printf("Active OpenFlow connection methods:\n");
printf(" tcp:IP[:PORT] "
- "PORT (default: %d) at remote IP\n", OFP_TCP_PORT);
+ "PORT (default: %d) at remote IP\n", OFP_PORT);
#ifdef HAVE_OPENSSL
printf(" ssl:IP[:PORT] "
- "SSL PORT (default: %d) at remote IP\n", OFP_TCP_PORT);
+ "SSL PORT (default: %d) at remote IP\n", OFP_PORT);
#endif
printf(" unix:FILE Unix domain socket named FILE\n");
}
printf("Passive OpenFlow connection methods:\n");
printf(" ptcp:[PORT][:IP] "
"listen to TCP PORT (default: %d) on IP\n",
- OFP_TCP_PORT);
+ OFP_PORT);
#ifdef HAVE_OPENSSL
printf(" pssl:[PORT][:IP] "
"listen for SSL on PORT (default: %d) on IP\n",
- OFP_TCP_PORT);
+ OFP_PORT);
#endif
printf(" punix:FILE "
"listen on Unix domain socket FILE\n");
}
/* Success. */
- ovs_assert(vconn->state != VCS_CONNECTING || vconn->class->connect);
+ ovs_assert(vconn->state != VCS_CONNECTING || vconn->vclass->connect);
*vconnp = vconn;
return 0;
vconn_connect(vconn);
}
- if (vconn->class->run) {
- (vconn->class->run)(vconn);
+ if (vconn->vclass->run) {
+ (vconn->vclass->run)(vconn);
}
}
vconn_connect_wait(vconn);
}
- if (vconn->class->run_wait) {
- (vconn->class->run_wait)(vconn);
+ if (vconn->vclass->run_wait) {
+ (vconn->vclass->run_wait)(vconn);
}
}
+/* Returns 0 if 'vconn' is healthy (connecting or connected), a positive errno
+ * value if the connection died abnormally (connection failed or aborted), or
+ * EOF if the connection was closed in a normal way. */
+int
+vconn_get_status(const struct vconn *vconn)
+{
+ return vconn->error == EAGAIN ? 0 : vconn->error;
+}
+
int
vconn_open_block(const char *name, uint32_t allowed_versions, uint8_t dscp,
struct vconn **vconnp)
{
if (vconn != NULL) {
char *name = vconn->name;
- (vconn->class->close)(vconn);
+ (vconn->vclass->close)(vconn);
free(name);
}
}
vconn->allowed_versions = allowed_versions;
}
-/* Returns the IP address of the peer, or 0 if the peer is not connected over
- * an IP-based protocol or if its IP address is not yet known. */
-ovs_be32
-vconn_get_remote_ip(const struct vconn *vconn)
-{
- return vconn->remote_ip;
-}
-
-/* Returns the transport port of the peer, or 0 if the connection does not
- * contain a port or if the port is not yet known. */
-ovs_be16
-vconn_get_remote_port(const struct vconn *vconn)
-{
- return vconn->remote_port;
-}
-
-/* Returns the IP address used to connect to the peer, or 0 if the
- * connection is not an IP-based protocol or if its IP address is not
- * yet known. */
-ovs_be32
-vconn_get_local_ip(const struct vconn *vconn)
-{
- return vconn->local_ip;
-}
-
-/* Returns the transport port used to connect to the peer, or 0 if the
- * connection does not contain a port or if the port is not yet known. */
-ovs_be16
-vconn_get_local_port(const struct vconn *vconn)
-{
- return vconn->local_port;
-}
-
/* Returns the OpenFlow version negotiated with the peer, or -1 if version
* negotiation is not yet complete.
*
static void
vcs_connecting(struct vconn *vconn)
{
- int retval = (vconn->class->connect)(vconn);
+ int retval = (vconn->vclass->connect)(vconn);
ovs_assert(retval != EINPROGRESS);
if (!retval) {
vconn->state = VCS_SEND_HELLO;
return vconn->error;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
} while (vconn->state != last_state);
type != OFPTYPE_ERROR &&
type != OFPTYPE_ECHO_REQUEST &&
type != OFPTYPE_ECHO_REPLY)) {
+ struct ofpbuf *reply;
+
VLOG_ERR_RL(&bad_ofmsg_rl, "%s: received OpenFlow version "
"0x%02"PRIx8" != expected %02x",
vconn->name, oh->version, vconn->version);
+
+ /* Send a "bad version" reply, if we can. */
+ reply = ofperr_encode_reply(OFPERR_OFPBRC_BAD_VERSION, oh);
+ retval = vconn_send(vconn, reply);
+ if (retval) {
+ VLOG_INFO_RL(&bad_ofmsg_rl,
+ "%s: failed to queue error reply (%s)",
+ vconn->name, ovs_strerror(retval));
+ ofpbuf_delete(reply);
+ }
+
+ /* Suppress the received message, as if it had not arrived. */
+ retval = EAGAIN;
ofpbuf_delete(msg);
- retval = EPROTO;
}
}
}
static int
do_recv(struct vconn *vconn, struct ofpbuf **msgp)
{
- int retval = (vconn->class->recv)(vconn, msgp);
+ int retval = (vconn->vclass->recv)(vconn, msgp);
if (!retval) {
COVERAGE_INC(vconn_received);
if (VLOG_IS_DBG_ENABLED()) {
ofpmsg_update_length(msg);
if (!VLOG_IS_DBG_ENABLED()) {
COVERAGE_INC(vconn_sent);
- retval = (vconn->class->send)(vconn, msg);
+ retval = (vconn->vclass->send)(vconn, msg);
} else {
char *s = ofp_to_string(msg->data, msg->size, 1);
- retval = (vconn->class->send)(vconn, msg);
+ retval = (vconn->vclass->send)(vconn, msg);
if (retval != EAGAIN) {
VLOG_DBG_RL(&ofmsg_rl, "%s: sent (%s): %s",
vconn->name, ovs_strerror(retval), s);
* All of the requests on 'requests' are always destroyed, regardless of the
* return value. */
int
-vconn_transact_multiple_noreply(struct vconn *vconn, struct list *requests,
+vconn_transact_multiple_noreply(struct vconn *vconn, struct ovs_list *requests,
struct ofpbuf **replyp)
{
struct ofpbuf *request, *next;
poll_immediate_wake();
return;
}
- (vconn->class->wait)(vconn, wait);
+ (vconn->vclass->wait)(vconn, wait);
}
void
{
if (pvconn != NULL) {
char *name = pvconn->name;
- (pvconn->class->close)(pvconn);
+ (pvconn->pvclass->close)(pvconn);
free(name);
}
}
int
pvconn_accept(struct pvconn *pvconn, struct vconn **new_vconn)
{
- int retval = (pvconn->class->accept)(pvconn, new_vconn);
+ int retval = (pvconn->pvclass->accept)(pvconn, new_vconn);
if (retval) {
*new_vconn = NULL;
} else {
ovs_assert((*new_vconn)->state != VCS_CONNECTING
- || (*new_vconn)->class->connect);
+ || (*new_vconn)->vclass->connect);
}
return retval;
}
void
pvconn_wait(struct pvconn *pvconn)
{
- (pvconn->class->wait)(pvconn);
+ (pvconn->pvclass->wait)(pvconn);
}
/* Initializes 'vconn' as a new vconn named 'name', implemented via 'class'.
int connect_status, const char *name, uint32_t allowed_versions)
{
memset(vconn, 0, sizeof *vconn);
- vconn->class = class;
+ vconn->vclass = class;
vconn->state = (connect_status == EAGAIN ? VCS_CONNECTING
: !connect_status ? VCS_SEND_HELLO
: VCS_DISCONNECTED);
ovs_assert(vconn->state != VCS_CONNECTING || class->connect);
}
-void
-vconn_set_remote_ip(struct vconn *vconn, ovs_be32 ip)
-{
- vconn->remote_ip = ip;
-}
-
-void
-vconn_set_remote_port(struct vconn *vconn, ovs_be16 port)
-{
- vconn->remote_port = port;
-}
-
-void
-vconn_set_local_ip(struct vconn *vconn, ovs_be32 ip)
-{
- vconn->local_ip = ip;
-}
-
-void
-vconn_set_local_port(struct vconn *vconn, ovs_be16 port)
-{
- vconn->local_port = port;
-}
-
void
pvconn_init(struct pvconn *pvconn, const struct pvconn_class *class,
const char *name, uint32_t allowed_versions)
{
- pvconn->class = class;
+ pvconn->pvclass = class;
pvconn->name = xstrdup(name);
pvconn->allowed_versions = allowed_versions;
}