Example #1
0
static void
parse_named_action(enum ofputil_action_code code, const struct flow *flow,
                   struct ofpbuf *b, char *arg)
{
    struct ofp_action_dl_addr *oada;
    struct ofp_action_vlan_pcp *oavp;
    struct ofp_action_vlan_vid *oavv;
    struct ofp_action_nw_addr *oana;
    struct ofp_action_tp_port *oata;

    switch (code) {
    case OFPUTIL_OFPAT_OUTPUT:
        parse_output(b, arg);
        break;

    case OFPUTIL_OFPAT_SET_VLAN_VID:
        oavv = ofputil_put_OFPAT_SET_VLAN_VID(b);
        oavv->vlan_vid = htons(str_to_u32(arg));
        break;

    case OFPUTIL_OFPAT_SET_VLAN_PCP:
        oavp = ofputil_put_OFPAT_SET_VLAN_PCP(b);
        oavp->vlan_pcp = str_to_u32(arg);
        break;

    case OFPUTIL_OFPAT_STRIP_VLAN:
        ofputil_put_OFPAT_STRIP_VLAN(b);
        break;

    case OFPUTIL_OFPAT_SET_DL_SRC:
    case OFPUTIL_OFPAT_SET_DL_DST:
        oada = ofputil_put_action(code, b);
        str_to_mac(arg, oada->dl_addr);
        break;

    case OFPUTIL_OFPAT_SET_NW_SRC:
    case OFPUTIL_OFPAT_SET_NW_DST:
        oana = ofputil_put_action(code, b);
        str_to_ip(arg, &oana->nw_addr);
        break;

    case OFPUTIL_OFPAT_SET_NW_TOS:
        ofputil_put_OFPAT_SET_NW_TOS(b)->nw_tos = str_to_u32(arg);
        break;

    case OFPUTIL_OFPAT_SET_TP_SRC:
    case OFPUTIL_OFPAT_SET_TP_DST:
        oata = ofputil_put_action(code, b);
        oata->tp_port = htons(str_to_u32(arg));
        break;

    case OFPUTIL_OFPAT_ENQUEUE:
        parse_enqueue(b, arg);
        break;

    case OFPUTIL_NXAST_RESUBMIT:
        parse_resubmit(b, arg);
        break;

    case OFPUTIL_NXAST_SET_TUNNEL:
        parse_set_tunnel(b, arg);
        break;

    case OFPUTIL_NXAST_SET_QUEUE:
        ofputil_put_NXAST_SET_QUEUE(b)->queue_id = htonl(str_to_u32(arg));
        break;

    case OFPUTIL_NXAST_POP_QUEUE:
        ofputil_put_NXAST_POP_QUEUE(b);
        break;

    case OFPUTIL_NXAST_REG_MOVE:
        nxm_parse_reg_move(ofputil_put_NXAST_REG_MOVE(b), arg);
        break;

    case OFPUTIL_NXAST_REG_LOAD:
        nxm_parse_reg_load(ofputil_put_NXAST_REG_LOAD(b), arg);
        break;

    case OFPUTIL_NXAST_NOTE:
        parse_note(b, arg);
        break;

    case OFPUTIL_NXAST_SET_TUNNEL64:
        ofputil_put_NXAST_SET_TUNNEL64(b)->tun_id = htonll(str_to_u64(arg));
        break;

    case OFPUTIL_NXAST_MULTIPATH:
        multipath_parse(ofputil_put_NXAST_MULTIPATH(b), arg);
        break;

    case OFPUTIL_NXAST_AUTOPATH:
        autopath_parse(ofputil_put_NXAST_AUTOPATH(b), arg);
        break;

    case OFPUTIL_NXAST_BUNDLE:
        bundle_parse(b, arg);
        break;

    case OFPUTIL_NXAST_BUNDLE_LOAD:
        bundle_parse_load(b, arg);
        break;

    case OFPUTIL_NXAST_RESUBMIT_TABLE:
    case OFPUTIL_NXAST_OUTPUT_REG:
        NOT_REACHED();

    case OFPUTIL_NXAST_LEARN:
        learn_parse(b, arg, flow);
        break;

    case OFPUTIL_NXAST_EXIT:
        ofputil_put_NXAST_EXIT(b);
        break;
    }
}
Example #2
0
void
learn_execute(const struct nx_action_learn *learn, const struct flow *flow,
              struct ofputil_flow_mod *fm)
{
    const void *p, *end;
    struct ofpbuf actions;

    cls_rule_init_catchall(&fm->cr, ntohs(learn->priority));
    fm->cookie = htonll(0);
    fm->cookie_mask = htonll(0);
    fm->new_cookie = learn->cookie;
    fm->table_id = learn->table_id;
    fm->command = OFPFC_MODIFY_STRICT;
    fm->idle_timeout = ntohs(learn->idle_timeout);
    fm->hard_timeout = ntohs(learn->hard_timeout);
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = ntohs(learn->flags) & OFPFF_SEND_FLOW_REM;
    fm->actions = NULL;
    fm->n_actions = 0;

    ofpbuf_init(&actions, 64);

    if (learn->fin_idle_timeout || learn->fin_hard_timeout) {
        struct nx_action_fin_timeout *naft;

        naft = ofputil_put_NXAST_FIN_TIMEOUT(&actions);
        naft->fin_idle_timeout = learn->fin_idle_timeout;
        naft->fin_hard_timeout = learn->fin_hard_timeout;
    }

    for (p = learn + 1, end = (char *) learn + ntohs(learn->len); p != end; ) {
        uint16_t header = ntohs(get_be16(&p));
        int n_bits = header & NX_LEARN_N_BITS_MASK;
        int src_type = header & NX_LEARN_SRC_MASK;
        int dst_type = header & NX_LEARN_DST_MASK;
        union mf_subvalue value;

        struct mf_subfield dst;
        int chunk, ofs;

        if (!header) {
            break;
        }

        if (src_type == NX_LEARN_SRC_FIELD) {
            struct mf_subfield src;

            get_subfield(n_bits, &p, &src);
            mf_read_subfield(&src, flow, &value);
        } else {
            int p_bytes = 2 * DIV_ROUND_UP(n_bits, 16);

            memset(&value, 0, sizeof value);
            bitwise_copy(p, p_bytes, 0,
                         &value, sizeof value, 0,
                         n_bits);
            p = (const uint8_t *) p + p_bytes;
        }

        switch (dst_type) {
        case NX_LEARN_DST_MATCH:
            get_subfield(n_bits, &p, &dst);
            mf_write_subfield(&dst, &value, &fm->cr);
            break;

        case NX_LEARN_DST_LOAD:
            get_subfield(n_bits, &p, &dst);
            for (ofs = 0; ofs < n_bits; ofs += chunk) {
                struct nx_action_reg_load *load;

                chunk = MIN(n_bits - ofs, 64);

                load = ofputil_put_NXAST_REG_LOAD(&actions);
                load->ofs_nbits = nxm_encode_ofs_nbits(dst.ofs + ofs, chunk);
                load->dst = htonl(dst.field->nxm_header);
                bitwise_copy(&value, sizeof value, ofs,
                             &load->value, sizeof load->value, 0,
                             chunk);
            }
            break;

        case NX_LEARN_DST_OUTPUT:
            if (n_bits <= 16 || is_all_zeros(value.u8, sizeof value - 2)) {
                ofputil_put_OFPAT10_OUTPUT(&actions)->port = value.be16[7];
            }
            break;
        }
    }

    fm->actions = ofpbuf_steal_data(&actions);
    fm->n_actions = actions.size / sizeof(struct ofp_action_header);
}
void
learn_execute(const struct nx_action_learn *learn, const struct flow *flow,
              struct ofputil_flow_mod *fm)
{
    const void *p, *end;
    struct ofpbuf actions;

    cls_rule_init_catchall(&fm->cr, ntohs(learn->priority));
    fm->cookie = learn->cookie;
    fm->table_id = learn->table_id;
    fm->command = OFPFC_MODIFY_STRICT;
    fm->idle_timeout = ntohs(learn->idle_timeout);
    fm->hard_timeout = ntohs(learn->hard_timeout);
    fm->buffer_id = UINT32_MAX;
    fm->out_port = OFPP_NONE;
    fm->flags = ntohs(learn->flags) & OFPFF_SEND_FLOW_REM;
    fm->actions = NULL;
    fm->n_actions = 0;

    ofpbuf_init(&actions, 64);

    for (p = learn + 1, end = (char *) learn + ntohs(learn->len); p != end; ) {
        uint16_t header = ntohs(get_be16(&p));
        int n_bits = header & NX_LEARN_N_BITS_MASK;
        int src_type = header & NX_LEARN_SRC_MASK;
        int dst_type = header & NX_LEARN_DST_MASK;
        uint64_t value;

        struct nx_action_reg_load *load;
        ovs_be32 dst_field;
        int dst_ofs;

        if (!header) {
            break;
        }

        if (src_type == NX_LEARN_SRC_FIELD) {
            ovs_be32 src_field = get_be32(&p);
            int src_ofs = ntohs(get_be16(&p));

            value = nxm_read_field_bits(src_field,
                                        nxm_encode_ofs_nbits(src_ofs, n_bits),
                                        flow);
        } else {
            value = get_bits(n_bits, &p);
        }

        switch (dst_type) {
        case NX_LEARN_DST_MATCH:
            dst_field = get_be32(&p);
            dst_ofs = ntohs(get_be16(&p));
            mf_set_subfield(mf_from_nxm_header(ntohl(dst_field)), value,
                            dst_ofs, n_bits, &fm->cr);
            break;

        case NX_LEARN_DST_LOAD:
            dst_field = get_be32(&p);
            dst_ofs = ntohs(get_be16(&p));
            load = ofputil_put_NXAST_REG_LOAD(&actions);
            load->ofs_nbits = nxm_encode_ofs_nbits(dst_ofs, n_bits);
            load->dst = dst_field;
            load->value = htonll(value);
            break;

        case NX_LEARN_DST_OUTPUT:
            ofputil_put_OFPAT_OUTPUT(&actions)->port = htons(value);
            break;
        }
    }

    fm->actions = ofpbuf_steal_data(&actions);
    fm->n_actions = actions.size / sizeof(struct ofp_action_header);
}