X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Frconn.c;h=2c49ca850d3c06446ef16ab72a55ca23aebdd684;hb=HEAD;hp=f7f90f7e5451ba0949c906cf210841c5ad5206ae;hpb=5ea1eab089607de8f87189fe4463364e26576070;p=sliver-openvswitch.git diff --git a/lib/rconn.c b/lib/rconn.c index f7f90f7e5..2c49ca850 100644 --- a/lib/rconn.c +++ b/lib/rconn.c @@ -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. @@ -115,17 +115,6 @@ struct rconn { int probe_interval; /* Secs of inactivity before sending probe. */ time_t last_activity; /* Last time we saw some activity. */ - /* When we create a vconn we obtain these values, to save them past the end - * of the vconn's lifetime. Otherwise, in-band control will only allow - * traffic when a vconn is actually open, but it is nice to allow ARP to - * complete even between connection attempts, and it is also polite to - * allow traffic from other switches to go through to the controller - * whether or not we are connected. - * - * We don't cache the local port, because that changes from one connection - * attempt to the next. */ - ovs_be32 local_ip, remote_ip; - ovs_be16 remote_port; uint8_t dscp; /* Messages sent or received are copied to the monitor connections. */ @@ -456,9 +445,6 @@ reconnect(struct rconn *rc) retval = vconn_open(rc->target, rc->allowed_versions, rc->dscp, &rc->vconn); if (!retval) { - rc->remote_ip = vconn_get_remote_ip(rc->vconn); - rc->local_ip = vconn_get_local_ip(rc->vconn); - rc->remote_port = vconn_get_remote_port(rc->vconn); rc->backoff_deadline = time_now() + rc->backoff; state_transition(rc, S_CONNECTING); } else { @@ -606,7 +592,15 @@ rconn_run(struct rconn *rc) ovs_mutex_lock(&rc->mutex); if (rc->vconn) { + int error; + vconn_run(rc->vconn); + + error = vconn_get_status(rc->vconn); + if (error) { + report_error(rc, error); + disconnect(rc, error); + } } for (i = 0; i < rc->n_monitors; ) { struct ofpbuf *msg; @@ -632,7 +626,7 @@ rconn_run(struct rconn *rc) STATES #undef STATE default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } while (rc->state != old_state); ovs_mutex_unlock(&rc->mutex); @@ -722,10 +716,14 @@ rconn_send__(struct rconn *rc, struct ofpbuf *b, if (rconn_is_connected(rc)) { COVERAGE_INC(rconn_queued); copy_to_monitor(rc, b); - b->private_p = counter; + if (counter) { - rconn_packet_counter_inc(counter, b->size); + rconn_packet_counter_inc(counter, ofpbuf_size(b)); } + + /* Reuse 'frame' as a private pointer while 'b' is in txq. */ + ofpbuf_set_frame(b, counter); + list_push_back(&rc->txq, &b->list_node); /* If the queue was empty before we added 'b', try to send some @@ -911,46 +909,6 @@ rconn_failure_duration(const struct rconn *rconn) return duration; } -/* Returns the IP address of the peer, or 0 if the peer's IP address is not - * known. */ -ovs_be32 -rconn_get_remote_ip(const struct rconn *rconn) -{ - return rconn->remote_ip; -} - -/* Returns the transport port of the peer, or 0 if the peer's port is not - * known. */ -ovs_be16 -rconn_get_remote_port(const struct rconn *rconn) -{ - return rconn->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 - * known. */ -ovs_be32 -rconn_get_local_ip(const struct rconn *rconn) -{ - return rconn->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 known. */ -ovs_be16 -rconn_get_local_port(const struct rconn *rconn) - OVS_EXCLUDED(rconn->mutex) -{ - ovs_be16 port; - - ovs_mutex_lock(&rconn->mutex); - port = rconn->vconn ? vconn_get_local_port(rconn->vconn) : 0; - ovs_mutex_unlock(&rconn->mutex); - - return port; -} - static int rconn_get_version__(const struct rconn *rconn) OVS_REQUIRES(rconn->mutex) @@ -1139,9 +1097,6 @@ rconn_set_target__(struct rconn *rc, const char *target, const char *name) rc->name = xstrdup(name ? name : target); free(rc->target); rc->target = xstrdup(target); - rc->local_ip = 0; - rc->remote_ip = 0; - rc->remote_port = 0; } /* Tries to send a packet from 'rc''s send buffer. Returns 0 if successful, @@ -1151,17 +1106,19 @@ try_send(struct rconn *rc) OVS_REQUIRES(rc->mutex) { struct ofpbuf *msg = ofpbuf_from_list(rc->txq.next); - unsigned int n_bytes = msg->size; - struct rconn_packet_counter *counter = msg->private_p; + unsigned int n_bytes = ofpbuf_size(msg); + struct rconn_packet_counter *counter = msg->frame; int retval; /* Eagerly remove 'msg' from the txq. We can't remove it from the list * after sending, if sending is successful, because it is then owned by the * vconn, which might have freed it already. */ list_remove(&msg->list_node); + ofpbuf_set_frame(msg, NULL); retval = vconn_send(rc->vconn, msg); if (retval) { + ofpbuf_set_frame(msg, counter); list_push_front(&rc->txq, &msg->list_node); if (retval != EAGAIN) { report_error(rc, retval); @@ -1254,9 +1211,9 @@ flush_queue(struct rconn *rc) } while (!list_is_empty(&rc->txq)) { struct ofpbuf *b = ofpbuf_from_list(list_pop_front(&rc->txq)); - struct rconn_packet_counter *counter = b->private_p; + struct rconn_packet_counter *counter = b->frame; if (counter) { - rconn_packet_counter_dec(counter, b->size); + rconn_packet_counter_dec(counter, ofpbuf_size(b)); } COVERAGE_INC(rconn_discarded); ofpbuf_delete(b); @@ -1280,7 +1237,7 @@ timeout(const struct rconn *rc) STATES #undef STATE default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -1349,13 +1306,24 @@ is_connected_state(enum state state) return (state & (S_ACTIVE | S_IDLE)) != 0; } +/* When a switch initially connects to a controller, the controller may spend a + * little time examining the switch, looking at, for example, its datapath ID, + * before it decides whether it is willing to control that switch. At that + * point, it either disconnects or starts controlling the switch. + * + * This function returns a guess to its caller about whether 'b' is OpenFlow + * message that indicates that the controller has decided to control the + * switch. It returns false if the message is one that a controller typically + * uses to determine whether a switch is admissible, true if the message is one + * that would typically be used only after the controller has admitted the + * switch. */ static bool is_admitted_msg(const struct ofpbuf *b) { enum ofptype type; enum ofperr error; - error = ofptype_decode(&type, b->data); + error = ofptype_decode(&type, ofpbuf_data(b)); if (error) { return false; } @@ -1370,7 +1338,6 @@ is_admitted_msg(const struct ofpbuf *b) case OFPTYPE_GET_CONFIG_REQUEST: case OFPTYPE_GET_CONFIG_REPLY: case OFPTYPE_SET_CONFIG: - /* FIXME: Change the following once they are implemented: */ case OFPTYPE_QUEUE_GET_CONFIG_REQUEST: case OFPTYPE_QUEUE_GET_CONFIG_REPLY: case OFPTYPE_GET_ASYNC_REQUEST: @@ -1383,6 +1350,8 @@ is_admitted_msg(const struct ofpbuf *b) case OFPTYPE_GROUP_FEATURES_STATS_REPLY: case OFPTYPE_TABLE_FEATURES_STATS_REQUEST: case OFPTYPE_TABLE_FEATURES_STATS_REPLY: + case OFPTYPE_BUNDLE_CONTROL: + case OFPTYPE_BUNDLE_ADD_MESSAGE: return false; case OFPTYPE_PACKET_IN: