Пример #1
0
struct ofpbuf *
flow_mod_conjunction(enum ofputil_protocol proto)
{
    struct ofputil_flow_mod fm;
    struct ofpbuf acts;
    struct ofpact_conjunction *a_conj;

    memset(&fm, 0, sizeof(fm));
    fm.command = OFPFC_ADD;
    fm.table_id = 4;
    fm.new_cookie = htonll(0x123456789abcdef0);
    fm.cookie_mask = OVS_BE64_MAX;
    fm.importance = 0x9878;

    fill_match(&fm.match);

    ofpbuf_init(&acts, 64);
    a_conj = ofpact_put_CONJUNCTION(&acts);
    a_conj->id = 0xabcdef;
    a_conj->clause = 1;
    a_conj->n_clauses = 2;

    fm.ofpacts = acts.data;
    fm.ofpacts_len = acts.size;
    return ofputil_encode_flow_mod(&fm, proto);
}
Пример #2
0
/* Parses 'string' as an OFPT_FLOW_MOD or NXT_FLOW_MOD with command 'command'
 * (one of OFPFC_*) and appends the parsed OpenFlow message to 'packets'.
 * '*cur_format' should initially contain the flow format currently configured
 * on the connection; this function will add a message to change the flow
 * format and update '*cur_format', if this is necessary to add the parsed
 * flow. */
void
parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
                       char *string, uint16_t command)
{
    bool is_del = command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT;
    enum nx_flow_format min_format, next_format;
    struct ofpbuf actions;
    struct ofpbuf *ofm;
    struct flow_mod fm;

    ofpbuf_init(&actions, 64);
    parse_ofp_str(&fm, NULL, is_del ? NULL : &actions, string);
    fm.command = command;

    min_format = ofputil_min_flow_format(&fm.cr, true, fm.cookie);
    next_format = MAX(*cur_format, min_format);
    if (next_format != *cur_format) {
        struct ofpbuf *sff = ofputil_make_set_flow_format(next_format);
        list_push_back(packets, &sff->list_node);
        *cur_format = next_format;
    }

    ofm = ofputil_encode_flow_mod(&fm, *cur_format);
    list_push_back(packets, &ofm->list_node);

    ofpbuf_uninit(&actions);
}
Пример #3
0
struct ofpbuf *
flow_mod_match_conj(enum ofputil_protocol proto)
{
    struct ofputil_flow_mod fm;
    struct ofpbuf acts;
    struct ofpact_ipv4 *a_set_field;
    struct ofpact_goto_table *a_goto;

    memset(&fm, 0, sizeof(fm));
    fm.command = OFPFC_ADD;
    fm.table_id = 3;
    fm.new_cookie = htonll(0x123456789abcdef0);
    fm.cookie_mask = OVS_BE64_MAX;
    fm.importance = 0x9878;

    match_init_catchall(&fm.match);
    match_set_conj_id(&fm.match, 0xabcdef);

    ofpbuf_init(&acts, 64);
    ofpact_put_STRIP_VLAN(&acts);
    a_set_field = ofpact_put_SET_IPV4_DST(&acts);
    a_set_field->ipv4 = inet_addr("192.168.2.9");
    a_goto = ofpact_put_GOTO_TABLE(&acts);
    a_goto->table_id = 100;

    fm.ofpacts = acts.data;
    fm.ofpacts_len = acts.size;
    return ofputil_encode_flow_mod(&fm, proto);
}
Пример #4
0
void
ofputil_encode_bundle_msgs(const struct ofputil_bundle_msg *bms,
                           size_t n_bms, struct ovs_list *requests,
                           enum ofputil_protocol protocol)
{
    enum ofp_version version = ofputil_protocol_to_ofp_version(protocol);

    for (size_t i = 0; i < n_bms; i++) {
        struct ofpbuf *request = NULL;

        switch ((int)bms[i].type) {
        case OFPTYPE_FLOW_MOD:
            request = ofputil_encode_flow_mod(&bms[i].fm, protocol);
            break;
        case OFPTYPE_GROUP_MOD:
            request = ofputil_encode_group_mod(version, &bms[i].gm, NULL, -1);
            break;
        case OFPTYPE_PACKET_OUT:
            request = ofputil_encode_packet_out(&bms[i].po, protocol);
            break;
        default:
            break;
        }
        if (request) {
            ovs_list_push_back(requests, &request->list_node);
        }
    }
}
Пример #5
0
struct ofpbuf *
flow_mod(enum ofputil_protocol proto)
{
    struct ofputil_flow_mod fm;
    struct ofpbuf acts;
    struct ofpact_ipv4 *a_set_field;
    struct ofpact_goto_table *a_goto;
    char *error;

    /*
     * Taken from neutron OVS-agent,
     * modified for OF>=1.3. (NXM -> OXM)
     * NOTE(yamamoto): This needs to be writable.  learn_parse() modifies it.
     */
    char learn_args[] =
        "table=99,"
        "priority=1,"
        "hard_timeout=300,"
        "OXM_OF_VLAN_VID[0..11],"
        "OXM_OF_ETH_DST[]=OXM_OF_ETH_SRC[],"
        "load:0->OXM_OF_VLAN_VID[],"
        "load:OXM_OF_TUNNEL_ID[]->OXM_OF_TUNNEL_ID[],"
        "output:OXM_OF_IN_PORT[]";

    memset(&fm, 0, sizeof(fm));
    fm.command = OFPFC_ADD;
    fm.table_id = 2;
    fm.new_cookie = htonll(0x123456789abcdef0);
    fm.cookie_mask = OVS_BE64_MAX;
    fm.importance = 0x9878;

    fill_match(&fm.match);

    ofpbuf_init(&acts, 64);
    ofpact_put_STRIP_VLAN(&acts);
    a_set_field = ofpact_put_SET_IPV4_DST(&acts);
    a_set_field->ipv4 = inet_addr("192.168.2.9");
    error = learn_parse(learn_args, &acts);
    assert(error == NULL);
    a_goto = ofpact_put_GOTO_TABLE(&acts);
    a_goto->table_id = 100;

    fm.ofpacts = acts.data;
    fm.ofpacts_len = acts.size;
    return ofputil_encode_flow_mod(&fm, proto);
}
Пример #6
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;
}
Пример #7
0
OfpBuf
FlowExecutor::EncodeMod<FlowEdit::Entry>(const FlowEdit::Entry& edit,
                                         int ofVersion) {
    ofputil_protocol proto =
        ofputil_protocol_from_ofp_version((ofp_version)ofVersion);
    assert(ofputil_protocol_is_valid(proto));

    FlowEdit::type mod = edit.first;
    ofputil_flow_stats& flow = *(edit.second->entry);

    ofputil_flow_mod flowMod;
    memset(&flowMod, 0, sizeof(flowMod));
    flowMod.table_id = flow.table_id;
    flowMod.priority = flow.priority;
    if (mod != FlowEdit::ADD) {
        flowMod.cookie = flow.cookie;
        flowMod.cookie_mask = ~((uint64_t)0);
    }
    flowMod.new_cookie = mod == FlowEdit::MOD ? OVS_BE64_MAX :
            (mod == FlowEdit::ADD ? flow.cookie : 0);
    memcpy(&flowMod.match, &flow.match, sizeof(flow.match));
    if (mod != FlowEdit::DEL) {
        flowMod.ofpacts_len = flow.ofpacts_len;
        flowMod.ofpacts = (ofpact*)flow.ofpacts;
    }
    flowMod.command = mod == FlowEdit::ADD ? OFPFC_ADD :
            (mod == FlowEdit::MOD ? OFPFC_MODIFY_STRICT : OFPFC_DELETE_STRICT);
    /* fill out defaults */
    flowMod.modify_cookie = false;
    flowMod.idle_timeout = OFP_FLOW_PERMANENT;
    flowMod.hard_timeout = OFP_FLOW_PERMANENT;
    flowMod.buffer_id = UINT32_MAX;
    flowMod.out_port = OFPP_NONE;
    flowMod.out_group = OFPG_ANY;
    flowMod.flags = (ofputil_flow_mod_flags)0;
    if (flow.flags)
        flowMod.flags = flow.flags;

    return OfpBuf(ofputil_encode_flow_mod(&flowMod, proto));
}
Пример #8
0
/* Parses 'string' as an OFPT_FLOW_MOD or NXT_FLOW_MOD with command 'command'
 * (one of OFPFC_*) and appends the parsed OpenFlow message to 'packets'.
 * '*cur_format' should initially contain the flow format currently configured
 * on the connection; this function will add a message to change the flow
 * format and update '*cur_format', if this is necessary to add the parsed
 * flow. */
void
parse_ofp_flow_mod_str(struct list *packets, enum nx_flow_format *cur_format,
                       bool *flow_mod_table_id, char *string, uint16_t command,
                       bool verbose)
{
    enum nx_flow_format min_format, next_format;
    struct cls_rule rule_copy;
    struct ofpbuf *ofm;
    struct ofputil_flow_mod fm;

    parse_ofp_str(&fm, command, string, verbose);

    min_format = ofputil_min_flow_format(&fm.cr);
    if (command != OFPFC_ADD && fm.cookie_mask != htonll(0)) {
        min_format = NXFF_NXM;
    }
    next_format = MAX(*cur_format, min_format);
    if (next_format != *cur_format) {
        struct ofpbuf *sff = ofputil_make_set_flow_format(next_format);
        list_push_back(packets, &sff->list_node);
        *cur_format = next_format;
    }

    /* Normalize a copy of the rule.  This ensures that non-normalized flows
     * get logged but doesn't affect what gets sent to the switch, so that the
     * switch can do whatever it likes with the flow. */
    rule_copy = fm.cr;
    ofputil_normalize_rule(&rule_copy, next_format);

    if (fm.table_id != 0xff && !*flow_mod_table_id) {
        struct ofpbuf *sff = ofputil_make_flow_mod_table_id(true);
        list_push_back(packets, &sff->list_node);
        *flow_mod_table_id = true;
    }

    ofm = ofputil_encode_flow_mod(&fm, *cur_format, *flow_mod_table_id);
    list_push_back(packets, &ofm->list_node);
}