Setting tag sliver-openvswitch-2.2.90-1
[sliver-openvswitch.git] / lib / vconn.c
index 5708987..c24e87d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -293,6 +293,15 @@ vconn_run_wait(struct vconn *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)
@@ -350,39 +359,6 @@ vconn_set_allowed_versions(struct vconn *vconn, uint32_t allowed_versions)
     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.
  *
@@ -480,16 +456,16 @@ vcs_recv_hello(struct vconn *vconn)
         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);
             }
@@ -519,7 +495,7 @@ vcs_recv_hello(struct vconn *vconn)
             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);
@@ -596,7 +572,7 @@ vconn_connect(struct vconn *vconn)
             return vconn->error;
 
         default:
-            NOT_REACHED();
+            OVS_NOT_REACHED();
         }
     } while (vconn->state != last_state);
 
@@ -622,20 +598,34 @@ vconn_recv(struct vconn *vconn, struct ofpbuf **msgp)
         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;
             }
         }
     }
@@ -651,7 +641,7 @@ do_recv(struct vconn *vconn, struct ofpbuf **msgp)
     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);
         }
@@ -684,14 +674,14 @@ do_send(struct vconn *vconn, struct ofpbuf *msg)
 {
     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",
@@ -773,7 +763,7 @@ vconn_recv_xid(struct vconn *vconn, ovs_be32 xid, struct ofpbuf **replyp)
             *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;
@@ -800,7 +790,7 @@ int
 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;
@@ -834,7 +824,7 @@ vconn_transact_noreply(struct vconn *vconn, struct ofpbuf *request,
     *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);
@@ -843,7 +833,7 @@ vconn_transact_noreply(struct vconn *vconn, struct ofpbuf *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);
@@ -862,7 +852,7 @@ vconn_transact_noreply(struct vconn *vconn, struct ofpbuf *request,
             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 "
@@ -1123,30 +1113,6 @@ vconn_init(struct vconn *vconn, const struct vconn_class *class,
     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)