/* Takes care of necessary 'sw' activity, except for receiving packets (which * the caller must do). */ void lswitch_run(struct lswitch *sw) { int i; rconn_run(sw->rconn); if (sw->state == S_CONNECTING) { if (rconn_get_version(sw->rconn) != -1) { lswitch_handshake(sw); sw->state = S_FEATURES_REPLY; } return; } for (i = 0; i < 50; i++) { struct ofpbuf *msg; msg = rconn_recv(sw->rconn); if (!msg) { break; } lswitch_process_packet(sw, msg); ofpbuf_delete(msg); } }
static void run_S_NEW(void) { struct ofpbuf *buf = ofpraw_alloc(OFPRAW_NXT_TLV_TABLE_REQUEST, rconn_get_version(swconn), 0); xid = queue_msg(buf); state = S_TLV_TABLE_REQUESTED; }
static void get_switch_config(struct rconn *swconn) { struct ofpbuf *request; request = ofpraw_alloc(OFPRAW_OFPT_GET_CONFIG_REQUEST, rconn_get_version(swconn), 0); queue_msg(request); }
static void set_switch_config(struct rconn *swconn, const struct ofp_switch_config *config) { struct ofpbuf *request; request = ofpraw_alloc(OFPRAW_OFPT_SET_CONFIG, rconn_get_version(swconn), 0); ofpbuf_put(request, config, sizeof *config); queue_msg(request); }
static void send_controller_id(struct lswitch *sw) { struct ofpbuf *b; int ofp_version = rconn_get_version(sw->rconn); ovs_assert(ofp_version > 0 && ofp_version < 0xff); b = ofpraw_alloc(OFPRAW_NXT_SET_CONTROLLER_ID, ofp_version, 0); struct nx_controller_id *nci = ofpbuf_put_zeros(b, sizeof *nci); nci->controller_id = htons(100); queue_tx(sw, b); }
static void lswitch_handshake(struct lswitch *sw) { enum ofputil_protocol protocol; enum ofp_version version; send_features_request(sw); send_controller_id(sw); version = rconn_get_version(sw->rconn); protocol = ofputil_protocol_from_ofp_version(version); if (sw->default_flows) { struct ofpbuf *msg = NULL; int error = 0; size_t i; if (!(protocol & sw->usable_protocols)) { enum ofputil_protocol want = rightmost_1bit(sw->usable_protocols); while (!error) { msg = ofputil_encode_set_protocol(protocol, want, &protocol); if (!msg) { break; } error = rconn_send(sw->rconn, msg, NULL); } } if (protocol & sw->usable_protocols) { for (i = 0; !error && i < sw->n_default_flows; i++) { msg = ofputil_encode_flow_mod(&sw->default_flows[i], protocol); error = rconn_send(sw->rconn, msg, NULL); } if (error) { VLOG_INFO_RL(&rl, "%s: failed to queue default flows (%s)", rconn_get_name(sw->rconn), ovs_strerror(error)); } } else { VLOG_INFO_RL(&rl, "%s: failed to set usable protocol", rconn_get_name(sw->rconn)); } } sw->protocol = protocol; }
static void send_features_request(struct lswitch *sw) { struct ofpbuf *b; int ofp_version = rconn_get_version(sw->rconn); ovs_assert(ofp_version > 0 && ofp_version < 0xff); /* Send OFPT_FEATURES_REQUEST. */ b = ofpraw_alloc(OFPRAW_OFPT_FEATURES_REQUEST, ofp_version, 0); queue_tx(sw, b); /* Send OFPT_SET_CONFIG. */ struct ofputil_switch_config config = { .miss_send_len = OFP_DEFAULT_MISS_SEND_LEN }; queue_tx(sw, ofputil_encode_set_config(&config, ofp_version)); }