static void ofservice_reconfigure(struct ofservice *,
const struct ofproto_controller *);
-static int ofservice_create(struct connmgr *, const char *target, uint8_t dscp);
+static int ofservice_create(struct connmgr *mgr, const char *target,
+ uint32_t allowed_versions, uint8_t dscp);
static void ofservice_destroy(struct connmgr *, struct ofservice *);
static struct ofservice *ofservice_lookup(struct connmgr *,
const char *target);
struct vconn *vconn;
int retval;
- retval = pvconn_accept(ofservice->pvconn, OFP10_VERSION, &vconn);
+ retval = pvconn_accept(ofservice->pvconn, &vconn);
if (!retval) {
struct rconn *rconn;
char *name;
/* Passing default value for creation of the rconn */
- rconn = rconn_create(ofservice->probe_interval, 0, ofservice->dscp);
+ rconn = rconn_create(ofservice->probe_interval, 0, ofservice->dscp,
+ vconn_get_allowed_versions(vconn));
name = ofconn_make_name(mgr, vconn_get_name(vconn));
rconn_connect_unreliably(rconn, vconn, name);
free(name);
struct vconn *vconn;
int retval;
- retval = pvconn_accept(mgr->snoops[i], OFP10_VERSION, &vconn);
+ retval = pvconn_accept(mgr->snoops[i], &vconn);
if (!retval) {
add_snooper(mgr, vconn);
} else if (retval != EAGAIN) {
\f
/* OpenFlow configuration. */
-static void add_controller(struct connmgr *, const char *target, uint8_t dscp);
+static void add_controller(struct connmgr *, const char *target, uint8_t dscp,
+ uint32_t allowed_versions);
static struct ofconn *find_controller_by_target(struct connmgr *,
const char *target);
static void update_fail_open(struct connmgr *);
void
connmgr_set_controllers(struct connmgr *mgr,
const struct ofproto_controller *controllers,
- size_t n_controllers)
+ size_t n_controllers, uint32_t allowed_versions)
{
bool had_controllers = connmgr_has_controllers(mgr);
struct shash new_controllers;
if (!find_controller_by_target(mgr, c->target)) {
VLOG_INFO("%s: added primary controller \"%s\"",
mgr->name, c->target);
- add_controller(mgr, c->target, c->dscp);
+ add_controller(mgr, c->target, c->dscp, allowed_versions);
}
} else if (!pvconn_verify_name(c->target)) {
if (!ofservice_lookup(mgr, c->target)) {
VLOG_INFO("%s: added service controller \"%s\"",
mgr->name, c->target);
- ofservice_create(mgr, c->target, c->dscp);
+ ofservice_create(mgr, c->target, allowed_versions, c->dscp);
}
} else {
VLOG_WARN_RL(&rl, "%s: unsupported controller \"%s\"",
/* Creates a new controller for 'target' in 'mgr'. update_controller() needs
* to be called later to finish the new ofconn's configuration. */
static void
-add_controller(struct connmgr *mgr, const char *target, uint8_t dscp)
+add_controller(struct connmgr *mgr, const char *target, uint8_t dscp,
+ uint32_t allowed_versions)
{
char *name = ofconn_make_name(mgr, target);
struct ofconn *ofconn;
- ofconn = ofconn_create(mgr, rconn_create(5, 8, dscp), OFCONN_PRIMARY, true);
+ ofconn = ofconn_create(mgr, rconn_create(5, 8, dscp, allowed_versions),
+ OFCONN_PRIMARY, true);
ofconn->pktbuf = pktbuf_create();
rconn_connect(ofconn->rconn, target, name);
hmap_insert(&mgr->controllers, &ofconn->hmap_node, hash_string(target, 0));
SSET_FOR_EACH (name, sset) {
struct pvconn *pvconn;
int error;
-
- error = pvconn_open(name, &pvconn, 0);
+ error = pvconn_open(name, 0, &pvconn, 0);
if (!error) {
pvconns[n_pvconns++] = pvconn;
} else {
/* Returns the currently configured protocol for 'ofconn', one of OFPUTIL_P_*.
*
- * The default, if no other format has been set, is OFPUTIL_P_OPENFLOW10. */
+ * Returns OFPUTIL_P_NONE, which is not a valid protocol, if 'ofconn' hasn't
+ * completed version negotiation. This can't happen if at least one OpenFlow
+ * message, other than OFPT_HELLO, has been received on the connection (such as
+ * in ofproto.c's message handling code), since version negotiation is a
+ * prerequisite for starting to receive messages. This means that
+ * OFPUTIL_P_NONE is a special case that most callers need not worry about. */
enum ofputil_protocol
-ofconn_get_protocol(struct ofconn *ofconn)
-{
+ofconn_get_protocol(const struct ofconn *ofconn)
+{
+ if (ofconn->protocol == OFPUTIL_P_NONE &&
+ rconn_is_connected(ofconn->rconn)) {
+ int version = rconn_get_version(ofconn->rconn);
+ if (version > 0) {
+ ofconn_set_protocol(CONST_CAST(struct ofconn *, ofconn),
+ ofputil_protocol_from_ofp_version(version));
+ }
+ }
+
return ofconn->protocol;
}
int i;
ofconn->role = NX_ROLE_OTHER;
- ofconn->protocol = OFPUTIL_P_OF10;
+ ofconn_set_protocol(ofconn, OFPUTIL_P_NONE);
ofconn->packet_in_format = NXPIF_OPENFLOW10;
/* Disassociate 'ofconn' from all of the ofopgroups that it initiated that
assert(reason < 32);
assert((unsigned int) type < OAM_N_TYPES);
- if (!rconn_is_connected(ofconn->rconn)) {
+ if (ofconn_get_protocol(ofconn) == OFPUTIL_P_NONE
+ || !rconn_is_connected(ofconn->rconn)) {
return false;
}
if (ofconn_receives_async_msg(ofconn, OAM_PORT_STATUS, reason)) {
struct ofpbuf *msg;
- msg = ofputil_encode_port_status(&ps, ofconn->protocol);
+ msg = ofputil_encode_port_status(&ps, ofconn_get_protocol(ofconn));
ofconn_send(ofconn, msg, NULL);
}
}
* also prevents new flows from being added (and expiring). (It
* also prevents processing OpenFlow requests that would not add
* new flows, so it is imperfect.) */
- msg = ofputil_encode_flow_removed(fr, ofconn->protocol);
+ msg = ofputil_encode_flow_removed(fr, ofconn_get_protocol(ofconn));
ofconn_send_reply(ofconn, msg);
}
}
* while (until a later call to pinsched_run()). */
pinsched_send(ofconn->schedulers[pin.reason == OFPR_NO_MATCH ? 0 : 1],
pin.fmd.in_port,
- ofputil_encode_packet_in(&pin, ofconn->protocol,
+ ofputil_encode_packet_in(&pin, ofconn_get_protocol(ofconn),
ofconn->packet_in_format),
do_send_packet_in, ofconn);
}
* ofservice_reconfigure() must be called to fully configure the new
* ofservice. */
static int
-ofservice_create(struct connmgr *mgr, const char *target, uint8_t dscp)
+ofservice_create(struct connmgr *mgr, const char *target,
+ uint32_t allowed_versions, uint8_t dscp)
{
struct ofservice *ofservice;
struct pvconn *pvconn;
int error;
- error = pvconn_open(target, &pvconn, dscp);
+ error = pvconn_open(target, allowed_versions, &pvconn, dscp);
if (error) {
return error;
}