示例#1
0
static void
set_field_parse(const char *arg, struct ofpbuf *ofpacts)
{
    char *orig = xstrdup(arg);
    struct ofpact_reg_load *load = ofpact_put_REG_LOAD(ofpacts);
    char *value;
    char *delim;
    char *key;
    const struct mf_field *mf;
    const char *error;
    union mf_value mf_value;

    value = orig;
    delim = strstr(orig, "->");
    if (!delim) {
        ovs_fatal(0, "%s: missing `->'", orig);
    }
    if (strlen(delim) <= strlen("->")) {
        ovs_fatal(0, "%s: missing field name following `->'", orig);
    }

    key = delim + strlen("->");
    mf = mf_from_name(key);
    if (!mf) {
        ovs_fatal(0, "%s is not valid oxm field name", key);
    }
    if (!mf->writable) {
        ovs_fatal(0, "%s is not allowed to set", key);
    }

    delim[0] = '\0';
    error = mf_parse_value(mf, value, &mf_value);
    if (error) {
        ovs_fatal(0, "%s", error);
    }
    if (!mf_is_value_valid(mf, &mf_value)) {
        ovs_fatal(0, "%s is not valid valid for field %s", value, key);
    }
    ofpact_set_field_init(load, mf, &mf_value);
    free(orig);
}
示例#2
0
/* Parses a specification of a flow from 's' into 'flow'.  's' must take the
 * form FIELD=VALUE[,FIELD=VALUE]... where each FIELD is the name of a
 * mf_field.  Fields must be specified in a natural order for satisfying
 * prerequisites.
 *
 * Returns NULL on success, otherwise a malloc()'d string that explains the
 * problem. */
char *
parse_ofp_exact_flow(struct flow *flow, const char *s)
{
    char *pos, *key, *value_s;
    char *error = NULL;
    char *copy;

    memset(flow, 0, sizeof *flow);

    pos = copy = xstrdup(s);
    while (ofputil_parse_key_value(&pos, &key, &value_s)) {
        const struct protocol *p;
        if (parse_protocol(key, &p)) {
            if (flow->dl_type) {
                error = xasprintf("%s: Ethernet type set multiple times", s);
                goto exit;
            }
            flow->dl_type = htons(p->dl_type);

            if (p->nw_proto) {
                if (flow->nw_proto) {
                    error = xasprintf("%s: network protocol set "
                                      "multiple times", s);
                    goto exit;
                }
                flow->nw_proto = p->nw_proto;
            }
        } else {
            const struct mf_field *mf;
            union mf_value value;
            char *field_error;

            mf = mf_from_name(key);
            if (!mf) {
                error = xasprintf("%s: unknown field %s", s, key);
                goto exit;
            }

            if (!mf_are_prereqs_ok(mf, flow)) {
                error = xasprintf("%s: prerequisites not met for setting %s",
                                  s, key);
                goto exit;
            }

            if (!mf_is_zero(mf, flow)) {
                error = xasprintf("%s: field %s set multiple times", s, key);
                goto exit;
            }

            field_error = mf_parse_value(mf, value_s, &value);
            if (field_error) {
                error = xasprintf("%s: bad value for %s (%s)",
                                  s, key, field_error);
                free(field_error);
                goto exit;
            }

            mf_set_flow_value(mf, &value, flow);
        }
    }

    if (!flow->in_port.ofp_port) {
        flow->in_port.ofp_port = OFPP_NONE;
    }

exit:
    free(copy);

    if (error) {
        memset(flow, 0, sizeof *flow);
    }
    return error;
}
示例#3
0
文件: learn.c 项目: Altiscale/ovs
/* Returns NULL if successful, otherwise a malloc()'d string describing the
 * error.  The caller is responsible for freeing the returned string. */
static char * OVS_WARN_UNUSED_RESULT
learn_parse_spec(const char *orig, char *name, char *value,
                 struct ofpact_learn_spec *spec)
{
    if (mf_from_name(name)) {
        const struct mf_field *dst = mf_from_name(name);
        union mf_value imm;
        char *error;

        error = mf_parse_value(dst, value, &imm);
        if (error) {
            return error;
        }

        spec->n_bits = dst->n_bits;
        spec->src_type = NX_LEARN_SRC_IMMEDIATE;
        memset(&spec->src_imm, 0, sizeof spec->src_imm);
        memcpy(&spec->src_imm.u8[sizeof spec->src_imm - dst->n_bytes],
               &imm, dst->n_bytes);
        spec->dst_type = NX_LEARN_DST_MATCH;
        spec->dst.field = dst;
        spec->dst.ofs = 0;
        spec->dst.n_bits = dst->n_bits;
    } else if (strchr(name, '[')) {
        /* Parse destination and check prerequisites. */
        char *error;

        error = mf_parse_subfield(&spec->dst, name);
        if (error) {
            return error;
        }
        if (!mf_nxm_header(spec->dst.field->id)) {
            return xasprintf("%s: experimenter OXM field '%s' not supported",
                             orig, name);
        }

        /* Parse source and check prerequisites. */
        if (value[0] != '\0') {
            error = mf_parse_subfield(&spec->src, value);
            if (error) {
                return error;
            }
            if (spec->src.n_bits != spec->dst.n_bits) {
                return xasprintf("%s: bit widths of %s (%u) and %s (%u) "
                                 "differ", orig, name, spec->src.n_bits, value,
                                 spec->dst.n_bits);
            }
        } else {
            spec->src = spec->dst;
        }

        spec->n_bits = spec->src.n_bits;
        spec->src_type = NX_LEARN_SRC_FIELD;
        spec->dst_type = NX_LEARN_DST_MATCH;
    } else if (!strcmp(name, "load")) {
        if (value[strcspn(value, "[-")] == '-') {
            char *error = learn_parse_load_immediate(value, spec);
            if (error) {
                return error;
            }
        } else {
            struct ofpact_reg_move move;
            char *error;

            error = nxm_parse_reg_move(&move, value);
            if (error) {
                return error;
            }

            spec->n_bits = move.src.n_bits;
            spec->src_type = NX_LEARN_SRC_FIELD;
            spec->src = move.src;
            spec->dst_type = NX_LEARN_DST_LOAD;
            spec->dst = move.dst;
        }
    } else if (!strcmp(name, "output")) {
        char *error = mf_parse_subfield(&spec->src, value);
        if (error) {
            return error;
        }

        spec->n_bits = spec->src.n_bits;
        spec->src_type = NX_LEARN_SRC_FIELD;
        spec->dst_type = NX_LEARN_DST_OUTPUT;
    } else {
        return xasprintf("%s: unknown keyword %s", orig, name);
    }

    return NULL;
}
示例#4
0
文件: learn.c 项目: yamt/openvswitch
static void
learn_parse_spec(const char *orig, char *name, char *value,
                 struct ofpact_learn_spec *spec)
{
    if (mf_from_name(name)) {
        const struct mf_field *dst = mf_from_name(name);
        union mf_value imm;
        char *error;

        error = mf_parse_value(dst, value, &imm);
        if (error) {
            ovs_fatal(0, "%s", error);
        }

        spec->n_bits = dst->n_bits;
        spec->src_type = NX_LEARN_SRC_IMMEDIATE;
        memset(&spec->src_imm, 0, sizeof spec->src_imm);
        memcpy(&spec->src_imm.u8[sizeof spec->src_imm - dst->n_bytes],
               &imm, dst->n_bytes);
        spec->dst_type = NX_LEARN_DST_MATCH;
        spec->dst.field = dst;
        spec->dst.ofs = 0;
        spec->dst.n_bits = dst->n_bits;
    } else if (strchr(name, '[')) {
        /* Parse destination and check prerequisites. */
        if (mf_parse_subfield(&spec->dst, name)[0] != '\0') {
            ovs_fatal(0, "%s: syntax error after NXM field name `%s'",
                      orig, name);
        }

        /* Parse source and check prerequisites. */
        if (value[0] != '\0') {
            if (mf_parse_subfield(&spec->src, value)[0] != '\0') {
                ovs_fatal(0, "%s: syntax error after NXM field name `%s'",
                          orig, value);
            }
            if (spec->src.n_bits != spec->dst.n_bits) {
                ovs_fatal(0, "%s: bit widths of %s (%u) and %s (%u) differ",
                          orig, name, spec->src.n_bits, value,
                          spec->dst.n_bits);
            }
        } else {
            spec->src = spec->dst;
        }

        spec->n_bits = spec->src.n_bits;
        spec->src_type = NX_LEARN_SRC_FIELD;
        spec->dst_type = NX_LEARN_DST_MATCH;
    } else if (!strcmp(name, "load")) {
        if (value[strcspn(value, "[-")] == '-') {
            learn_parse_load_immediate(value, spec);
        } else {
            struct ofpact_reg_move move;

            nxm_parse_reg_move(&move, value);

            spec->n_bits = move.src.n_bits;
            spec->src_type = NX_LEARN_SRC_FIELD;
            spec->src = move.src;
            spec->dst_type = NX_LEARN_DST_LOAD;
            spec->dst = move.dst;
        }
    } else if (!strcmp(name, "output")) {
        if (mf_parse_subfield(&spec->src, value)[0] != '\0') {
            ovs_fatal(0, "%s: syntax error after NXM field name `%s'",
                      orig, name);
        }

        spec->n_bits = spec->src.n_bits;
        spec->src_type = NX_LEARN_SRC_FIELD;
        spec->dst_type = NX_LEARN_DST_OUTPUT;
    } else {
        ovs_fatal(0, "%s: unknown keyword %s", orig, name);
    }
}
示例#5
0
文件: learn.c 项目: Grim-lock/ovs
/* Returns NULL if successful, otherwise a malloc()'d string describing the
 * error.  The caller is responsible for freeing the returned string. */
static char * OVS_WARN_UNUSED_RESULT
learn_parse_spec(const char *orig, char *name, char *value,
                 const struct ofputil_port_map *port_map,
                 struct ofpact_learn_spec *spec,
                 struct ofpbuf *ofpacts, struct match *match)
{
    /* Parse destination and check prerequisites. */
    struct mf_subfield dst;

    char *error = mf_parse_subfield(&dst, name);
    bool parse_error = error != NULL;
    free(error);

    if (!parse_error) {
        if (!mf_nxm_header(dst.field->id)) {
            return xasprintf("%s: experimenter OXM field '%s' not supported",
                             orig, name);
        }
        spec->dst = dst;
        spec->n_bits = dst.n_bits;
        spec->dst_type = NX_LEARN_DST_MATCH;

        /* Parse source and check prerequisites. */
        if (value[0] != '\0') {
            struct mf_subfield src;
            error = mf_parse_subfield(&src, value);
            if (error) {
                union mf_value imm;
                char *imm_error = NULL;

                /* Try an immediate value. */
                if (dst.ofs == 0 && dst.n_bits == dst.field->n_bits) {
                    /* Full field value. */
                    imm_error = mf_parse_value(dst.field, value, port_map,
                                               &imm);
                } else {
                    char *tail;
                    /* Partial field value. */
                    if (parse_int_string(value, (uint8_t *)&imm,
                                          dst.field->n_bytes, &tail)
                        || *tail != 0) {
                        imm_error = xasprintf("%s: cannot parse integer value", orig);
                    }

                    if (!imm_error &&
                        !bitwise_is_all_zeros(&imm, dst.field->n_bytes,
                                              dst.n_bits,
                                              dst.field->n_bytes * 8 - dst.n_bits)) {
                        struct ds ds;

                        ds_init(&ds);
                        mf_format(dst.field, &imm, NULL, NULL, &ds);
                        imm_error = xasprintf("%s: value %s does not fit into %d bits",
                                              orig, ds_cstr(&ds), dst.n_bits);
                        ds_destroy(&ds);
                    }
                }
                if (imm_error) {
                    char *err = xasprintf("%s: %s value %s cannot be parsed as a subfield (%s) or an immediate value (%s)",
                                          orig, name, value, error, imm_error);
                    free(error);
                    free(imm_error);
                    return err;
                }

                spec->src_type = NX_LEARN_SRC_IMMEDIATE;

                /* Update 'match' to allow for satisfying destination
                 * prerequisites. */
                mf_write_subfield_value(&dst, &imm, match);

                /* Push value last, as this may reallocate 'spec'! */
                unsigned int imm_bytes = DIV_ROUND_UP(dst.n_bits, 8);
                uint8_t *src_imm = ofpbuf_put_zeros(ofpacts,
                                                    OFPACT_ALIGN(imm_bytes));
                memcpy(src_imm, &imm, imm_bytes);

                free(error);
                return NULL;
            }
            spec->src = src;
            if (spec->src.n_bits != spec->dst.n_bits) {
                return xasprintf("%s: bit widths of %s (%u) and %s (%u) "
                                 "differ", orig, name, spec->src.n_bits, value,
                                 spec->dst.n_bits);
            }
        } else {
            spec->src = spec->dst;
        }

        spec->src_type = NX_LEARN_SRC_FIELD;
    } else if (!strcmp(name, "load")) {
        union mf_subvalue imm;
        char *tail;
        char *dst_value = strstr(value, "->");

        if (dst_value == value) {
            return xasprintf("%s: missing source before `->' in `%s'", name,
                             value);
        }
        if (!dst_value) {
            return xasprintf("%s: missing `->' in `%s'", name, value);
        }

        if (!parse_int_string(value, imm.u8, sizeof imm.u8, (char **) &tail)
            && tail != value) {
            if (tail != dst_value) {
                return xasprintf("%s: garbage before `->' in `%s'",
                                 name, value);
            }

            error = learn_parse_load_immediate(&imm, dst_value + 2, value, spec,
                                               ofpacts);
            if (error) {
                return error;
            }
        } else {
            struct ofpact_reg_move move;

            error = nxm_parse_reg_move(&move, value);
            if (error) {
                return error;
            }

            spec->n_bits = move.src.n_bits;
            spec->src_type = NX_LEARN_SRC_FIELD;
            spec->src = move.src;
            spec->dst_type = NX_LEARN_DST_LOAD;
            spec->dst = move.dst;
        }
    } else if (!strcmp(name, "output")) {
        error = mf_parse_subfield(&spec->src, value);
        if (error) {
            return error;
        }

        spec->n_bits = spec->src.n_bits;
        spec->src_type = NX_LEARN_SRC_FIELD;
        spec->dst_type = NX_LEARN_DST_OUTPUT;
    } else {
        return xasprintf("%s: unknown keyword %s", orig, name);
    }

    return NULL;
}
示例#6
0
文件: learn.c 项目: exuuwen/study
/* Returns NULL if successful, otherwise a malloc()'d string describing the
 * error.  The caller is responsible for freeing the returned string. */
static char * OVS_WARN_UNUSED_RESULT
learn_parse_spec(const char *orig, char *name, char *value,
                 struct ofpact_learn_spec *spec,
                 struct ofpbuf *ofpacts, struct match *match)
{
    if (mf_from_name(name)) {
        const struct mf_field *dst = mf_from_name(name);
        union mf_value imm;
        char *error;

        error = mf_parse_value(dst, value, &imm);
        if (error) {
            return error;
        }

        spec->n_bits = dst->n_bits;
        spec->src_type = NX_LEARN_SRC_IMMEDIATE;
        spec->dst_type = NX_LEARN_DST_MATCH;
        spec->dst.field = dst;
        spec->dst.ofs = 0;
        spec->dst.n_bits = dst->n_bits;

        /* Update 'match' to allow for satisfying destination
         * prerequisites. */
        mf_set_value(dst, &imm, match, NULL);

        /* Push value last, as this may reallocate 'spec'! */
        uint8_t *src_imm = ofpbuf_put_zeros(ofpacts,
                                            OFPACT_ALIGN(dst->n_bytes));
        memcpy(src_imm, &imm, dst->n_bytes);
    } else if (strchr(name, '[')) {
        /* Parse destination and check prerequisites. */
        char *error;

        error = mf_parse_subfield(&spec->dst, name);
        if (error) {
            return error;
        }
        if (!mf_nxm_header(spec->dst.field->id)) {
            return xasprintf("%s: experimenter OXM field '%s' not supported",
                             orig, name);
        }

        /* Parse source and check prerequisites. */
        if (value[0] != '\0') {
            error = mf_parse_subfield(&spec->src, value);
            if (error) {
                return error;
            }
            if (spec->src.n_bits != spec->dst.n_bits) {
                return xasprintf("%s: bit widths of %s (%u) and %s (%u) "
                                 "differ", orig, name, spec->src.n_bits, value,
                                 spec->dst.n_bits);
            }
        } else {
            spec->src = spec->dst;
        }

        spec->n_bits = spec->src.n_bits;
        spec->src_type = NX_LEARN_SRC_FIELD;
        spec->dst_type = NX_LEARN_DST_MATCH;
    } else if (!strcmp(name, "load")) {
        if (value[strcspn(value, "[-")] == '-') {
            char *error = learn_parse_load_immediate(value, spec, ofpacts);
            if (error) {
                return error;
            }
        } else {
            struct ofpact_reg_move move;
            char *error;

            error = nxm_parse_reg_move(&move, value);
            if (error) {
                return error;
            }

            spec->n_bits = move.src.n_bits;
            spec->src_type = NX_LEARN_SRC_FIELD;
            spec->src = move.src;
            spec->dst_type = NX_LEARN_DST_LOAD;
            spec->dst = move.dst;
        }
    } else if (!strcmp(name, "output")) {
        char *error = mf_parse_subfield(&spec->src, value);
        if (error) {
            return error;
        }

        spec->n_bits = spec->src.n_bits;
        spec->src_type = NX_LEARN_SRC_FIELD;
        spec->dst_type = NX_LEARN_DST_OUTPUT;
    } else {
        return xasprintf("%s: unknown keyword %s", orig, name);
    }

    return NULL;
}