/* Creates and returns a new learning switch. * * If 'learn_macs' is true, the new switch will learn the ports on which MAC * addresses appear. Otherwise, the new switch will flood all packets. * * If 'max_idle' is nonnegative, the new switch will set up flows that expire * after the given number of seconds (or never expire, if 'max_idle' is * OFP_FLOW_PERMANENT). Otherwise, the new switch will process every packet. * * The caller may provide the file stream 'default_flows' that defines * default flows that should be pushed when a switch connects. Each * line is a flow entry in the format described for "add-flows" command * in the Flow Syntax section of the ovs-ofct(8) man page. The caller * is responsible for closing the stream. * * 'rconn' is used to send out an OpenFlow features request. */ struct lswitch * lswitch_create(struct rconn *rconn, bool learn_macs, bool exact_flows, int max_idle, bool action_normal, FILE *default_flows) { struct lswitch *sw; sw = xzalloc(sizeof *sw); sw->max_idle = max_idle; sw->datapath_id = 0; sw->last_features_request = time_now() - 1; sw->ml = learn_macs ? mac_learning_create() : NULL; sw->action_normal = action_normal; if (exact_flows) { /* Exact match. */ sw->wildcards = 0; } else { /* We cannot wildcard all fields. * We need in_port to detect moves. * We need both SA and DA to do learning. */ sw->wildcards = (OFPFW_DL_TYPE | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_NW_PROTO | OFPFW_TP_SRC | OFPFW_TP_DST); } sw->queue = UINT32_MAX; sw->queued = rconn_packet_counter_create(); send_features_request(sw, rconn); if (default_flows) { send_default_flows(sw, rconn, default_flows); } return sw; }
static void handle_switch_ready( uint64_t datapath_id, void *user_data ) { UNUSED( user_data ); sw_entry *sw = update_sw_entry( &datapath_id ); debug( "Switch(%#" PRIx64 ") is connected.", datapath_id ); start_initial_discovery( sw ); send_features_request( sw ); }
/* Creates and returns a new mpls-enabled switch. * 'rconn' is used to send out an OpenFlow features request. */ struct mpls_switch * mpls_switch_create(struct rconn *rconn) { struct mpls_switch *sw; sw = xcalloc(1, sizeof *sw); sw->max_idle = OFP_FLOW_PERMANENT; // permanent flow sw->datapath_id = 0; sw->last_features_request = time_now() - 1; send_features_request(sw, rconn); return sw; }
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; }
/* Creates and returns a new learning switch. * * If 'learn_macs' is true, the new switch will learn the ports on which MAC * addresses appear. Otherwise, the new switch will flood all packets. * * If 'max_idle' is nonnegative, the new switch will set up flows that expire * after the given number of seconds (or never expire, if 'max_idle' is * OFP_FLOW_PERMANENT). Otherwise, the new switch will process every packet. * * 'rconn' is used to send out an OpenFlow features request. */ struct lswitch * lswitch_create(struct rconn *rconn, bool learn_macs, int max_idle) { struct lswitch *sw; size_t i; sw = xcalloc(1, sizeof *sw); sw->max_idle = max_idle; sw->datapath_id = 0; sw->last_features_request = time_now() - 1; sw->ml = learn_macs ? mac_learning_create() : NULL; sw->next_query = LLONG_MIN; sw->last_query = LLONG_MIN; sw->last_reply = LLONG_MIN; for (i = 0; i < STP_MAX_PORTS; i++) { sw->port_states[i] = P_DISABLED; } send_features_request(sw, rconn); return sw; }