/*
- * 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.
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_OLD_PORT);
#ifdef HAVE_OPENSSL
printf(" ssl:IP[:PORT] "
- "SSL PORT (default: %d) at remote IP\n", OFP_SSL_PORT);
+ "SSL PORT (default: %d) at remote IP\n", OFP_OLD_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_OLD_PORT);
#ifdef HAVE_OPENSSL
printf(" pssl:[PORT][:IP] "
"listen for SSL on PORT (default: %d) on IP\n",
- OFP_SSL_PORT);
+ OFP_OLD_PORT);
#endif
printf(" punix:FILE "
"listen on Unix domain socket FILE\n");
}
}
+/* 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)
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.
*
enum ofptype type;
enum ofperr error;
- error = ofptype_decode(&type, b->data);
+ error = ofptype_decode(&type, ofpbuf_data(b));
if (!error && type == OFPTYPE_HELLO) {
char *peer_s, *local_s;
uint32_t common_versions;
- if (!ofputil_decode_hello(b->data, &vconn->peer_versions)) {
+ if (!ofputil_decode_hello(ofpbuf_data(b), &vconn->peer_versions)) {
struct ds msg = DS_EMPTY_INITIALIZER;
ds_put_format(&msg, "%s: unknown data in hello:\n",
vconn->name);
- ds_put_hex_dump(&msg, b->data, b->size, 0, true);
+ ds_put_hex_dump(&msg, ofpbuf_data(b), ofpbuf_size(b), 0, true);
VLOG_WARN_RL(&bad_ofmsg_rl, "%s", ds_cstr(&msg));
ds_destroy(&msg);
}
ofpbuf_delete(b);
return;
} else {
- char *s = ofp_to_string(b->data, b->size, 1);
+ char *s = ofp_to_string(ofpbuf_data(b), ofpbuf_size(b), 1);
VLOG_WARN_RL(&bad_ofmsg_rl,
"%s: received message while expecting hello: %s",
vconn->name, s);
return vconn->error;
default:
- NOT_REACHED();
+ OVS_NOT_REACHED();
}
} while (vconn->state != last_state);
retval = do_recv(vconn, &msg);
}
if (!retval && !vconn->recv_any_version) {
- const struct ofp_header *oh = msg->data;
+ const struct ofp_header *oh = ofpbuf_data(msg);
if (oh->version != vconn->version) {
enum ofptype type;
- if (ofptype_decode(&type, msg->data)
+ if (ofptype_decode(&type, ofpbuf_data(msg))
|| (type != OFPTYPE_HELLO &&
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;
}
}
}
if (!retval) {
COVERAGE_INC(vconn_received);
if (VLOG_IS_DBG_ENABLED()) {
- char *s = ofp_to_string((*msgp)->data, (*msgp)->size, 1);
+ char *s = ofp_to_string(ofpbuf_data(*msgp), ofpbuf_size(*msgp), 1);
VLOG_DBG_RL(&ofmsg_rl, "%s: received: %s", vconn->name, s);
free(s);
}
{
int retval;
- ovs_assert(msg->size >= sizeof(struct ofp_header));
+ ovs_assert(ofpbuf_size(msg) >= sizeof(struct ofp_header));
ofpmsg_update_length(msg);
if (!VLOG_IS_DBG_ENABLED()) {
COVERAGE_INC(vconn_sent);
retval = (vconn->class->send)(vconn, msg);
} else {
- char *s = ofp_to_string(msg->data, msg->size, 1);
+ char *s = ofp_to_string(ofpbuf_data(msg), ofpbuf_size(msg), 1);
retval = (vconn->class->send)(vconn, msg);
if (retval != EAGAIN) {
VLOG_DBG_RL(&ofmsg_rl, "%s: sent (%s): %s",
*replyp = NULL;
return error;
}
- recv_xid = ((struct ofp_header *) reply->data)->xid;
+ recv_xid = ((struct ofp_header *) ofpbuf_data(reply))->xid;
if (xid == recv_xid) {
*replyp = reply;
return 0;
vconn_transact(struct vconn *vconn, struct ofpbuf *request,
struct ofpbuf **replyp)
{
- ovs_be32 send_xid = ((struct ofp_header *) request->data)->xid;
+ ovs_be32 send_xid = ((struct ofp_header *) ofpbuf_data(request))->xid;
int error;
*replyp = NULL;
*replyp = NULL;
/* Send request. */
- request_xid = ((struct ofp_header *) request->data)->xid;
+ request_xid = ((struct ofp_header *) ofpbuf_data(request))->xid;
error = vconn_send_block(vconn, request);
if (error) {
ofpbuf_delete(request);
/* Send barrier. */
barrier = ofputil_encode_barrier_request(vconn_get_version(vconn));
- barrier_xid = ((struct ofp_header *) barrier->data)->xid;
+ barrier_xid = ((struct ofp_header *) ofpbuf_data(barrier))->xid;
error = vconn_send_block(vconn, barrier);
if (error) {
ofpbuf_delete(barrier);
return error;
}
- msg_xid = ((struct ofp_header *) msg->data)->xid;
+ msg_xid = ((struct ofp_header *) ofpbuf_data(msg))->xid;
if (msg_xid == request_xid) {
if (*replyp) {
VLOG_WARN_RL(&bad_ofmsg_rl, "%s: duplicate replies with "
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)