Beispiel #1
0
/* 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;
}
Beispiel #2
0
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 );
}
Beispiel #3
0
/* 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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
/* 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;
}