/* Attempts to receive a packet from 'rc'. If successful, returns the packet; * otherwise, returns a null pointer. The caller is responsible for freeing * the packet (with ofpbuf_delete()). */ struct rfpbuf * rconn_recv(struct rconn *rc) { if (rc->state & (S_ACTIVE | S_IDLE)) { struct rfpbuf *buffer; int error = vconn_recv(rc->vconn, &buffer); if (!error) { if (rc->state == S_IDLE) { state_transition(rc, S_ACTIVE); } return buffer; } else if (error != EAGAIN) { if(error == ECONNRESET) { printf("The connection has been closed\n"); rconn_disconnect(rc); return NULL; } else { printf("An error has occured\n"); rconn_disconnect(rc); } } } return NULL; }
static void failover_periodic_cb(void *context_) { struct failover_context *context = context_; char *curr_peer = NULL; char *prev_peer = NULL; if (rconn_is_connected(context->remote_rconn)) return; if (!is_timed_out(context->peers[context->index], context->settings->max_backoff)) { return; } rconn_disconnect(context->remote_rconn); prev_peer = (char *)context->settings->controller_names[context->index]; context->index = (context->index + 1) % context->settings->num_controllers; curr_peer = (char *)context->settings->controller_names[context->index]; rconn_connect(context->remote_rconn, context->settings->controller_names[context->index]); context->peers[context->index]->epoch = time_now(); VLOG_INFO("Switching over to %s, from %s", curr_peer, prev_peer); }
/* Drops any existing connection on 'rc', then sets up 'rc' to connect to * 'target' and reconnect as needed. 'target' should be a remote OpenFlow * target in a form acceptable to vconn_open(). * * If 'name' is nonnull, then it is used in log messages in place of 'target'. * It should presumably give more information to a human reader than 'target', * but it need not be acceptable to vconn_open(). */ void rconn_connect(struct rconn *rc, const char *target) { rconn_disconnect(rc); rconn_set_target__(rc, target); reconnect(rc); }
/* Drops any existing connection on 'rc', then sets up 'rc' to connect to * 'target' and reconnect as needed. 'target' should be a remote OpenFlow * target in a form acceptable to vconn_open(). * * If 'name' is nonnull, then it is used in log messages in place of 'target'. * It should presumably give more information to a human reader than 'target', * but it need not be acceptable to vconn_open(). */ void rconn_connect(struct rconn *rc, const char *target, const char *name) { rconn_disconnect(rc); rconn_set_target__(rc, target, name); rc->reliable = true; reconnect(rc); }
int rconn_connect(struct rconn *rc, const char *name) { rconn_disconnect(rc); free(rc->name); rc->name = xstrdup(name); rc->reliable = true; return reconnect(rc); }
/* Drops any existing connection on 'rc', then configures 'rc' to use * 'vconn'. If the connection on 'vconn' drops, 'rc' will not reconnect on it * own. * * By default, the target obtained from vconn_get_name(vconn) is used in log * messages. If 'name' is nonnull, then it is used instead. It should * presumably give more information to a human reader than the target, but it * need not be acceptable to vconn_open(). */ void rconn_connect_unreliably(struct rconn *rc, struct vconn *vconn, const char *name) { assert(vconn != NULL); rconn_disconnect(rc); rconn_set_target__(rc, vconn_get_name(vconn)); // rc->reliable = false; rc->vconn = vconn; // rc->last_connected = time_now(); state_transition(rc, S_ACTIVE); }
void rconn_connect_unreliably(struct rconn *rc, const char *name, struct vconn *vconn) { assert(vconn != NULL); rconn_disconnect(rc); free(rc->name); rc->name = xstrdup(name); rc->reliable = false; rc->vconn = vconn; rc->last_connected = time_now(); state_transition(rc, S_ACTIVE); }
static void run_CONNECTING(struct rconn *rc) { int retval = vconn_connect(rc->vconn); if (!retval) { printf("%s: connected", rc->target); state_transition(rc, S_ACTIVE); } else if (retval != EAGAIN) { printf("%s: connection failed (%s)", rc->target, strerror(retval)); rconn_disconnect(rc); } }
/* Tries to send a packet from 'rc''s send buffer. Returns 0 if successful, * otherwise a positive errno value. */ static int try_send(struct rconn *rc, struct rfpbuf * msg) { int retval; retval = vconn_send(rc->vconn, msg); if(retval) { if(retval != EAGAIN) { rconn_disconnect(rc); } return retval; } return 0; }
static void reconnect(struct rconn *rc) { int retval; retval = vconn_open(rc->target, RFP10_VERSION, &rc->vconn, DSCP_DEFAULT); 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); state_transition(rc, S_CONNECTING); } else { printf("%s: connection failed (%s)", rc->target, strerror(retval)); rconn_disconnect(rc); } }
/* Processes 'msg', which should be an OpenFlow received on 'rconn', according * to the learning switch state in 'sw'. The most likely result of processing * is that flow-setup and packet-out OpenFlow messages will be sent out on * 'rconn'. */ static void lswitch_process_packet(struct lswitch *sw, const struct ofpbuf *msg) { enum ofptype type; struct ofpbuf b; b = *msg; if (ofptype_pull(&type, &b)) { return; } if (sw->state == S_FEATURES_REPLY && type != OFPTYPE_ECHO_REQUEST && type != OFPTYPE_FEATURES_REPLY) { return; } if (type == OFPTYPE_ECHO_REQUEST) { process_echo_request(sw, msg->data); } else if (type == OFPTYPE_FEATURES_REPLY) { if (sw->state == S_FEATURES_REPLY) { if (!process_switch_features(sw, msg->data)) { sw->state = S_SWITCHING; } else { rconn_disconnect(sw->rconn); } } } else if (type == OFPTYPE_PACKET_IN) { process_packet_in(sw, msg->data); } else if (type == OFPTYPE_FLOW_REMOVED) { /* Nothing to do. */ } else if (VLOG_IS_DBG_ENABLED()) { char *s = ofp_to_string(msg->data, msg->size, 2); VLOG_DBG_RL(&rl, "%016llx: OpenFlow packet ignored: %s", sw->datapath_id, s); free(s); } }