From: Ben Pfaff Date: Fri, 4 May 2012 16:52:37 +0000 (-0700) Subject: ofp-parse: New function parse_ofp_exact_flow(). X-Git-Tag: sliver-openvswitch-1.8.90-0~48^2~480 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=ccbe50f8f61ac944eb965f67c570d79b6724c9cf;p=sliver-openvswitch.git ofp-parse: New function parse_ofp_exact_flow(). This function parses a flow rather than a cls_rule. It will be useful for "ofproto/trace", which currently requires an odp_flow and thus can't accept values for registers and other concepts that don't exist in the kernel. Signed-off-by: Ben Pfaff --- diff --git a/lib/meta-flow.c b/lib/meta-flow.c index c1efbe2c1..8b60b35f1 100644 --- a/lib/meta-flow.c +++ b/lib/meta-flow.c @@ -1457,6 +1457,19 @@ mf_set_flow_value(const struct mf_field *mf, } } +/* Returns true if 'mf' has a zero value in 'flow', false if it is nonzero. + * + * The caller is responsible for ensuring that 'flow' meets 'mf''s + * prerequisites. */ +bool +mf_is_zero(const struct mf_field *mf, const struct flow *flow) +{ + union mf_value value; + + mf_get_value(mf, flow, &value); + return is_all_zeros((const uint8_t *) &value, mf->n_bytes); +} + /* Makes 'rule' wildcard field 'mf'. * * The caller is responsible for ensuring that 'rule' meets 'mf''s diff --git a/lib/meta-flow.h b/lib/meta-flow.h index 662778c74..632cb46dc 100644 --- a/lib/meta-flow.h +++ b/lib/meta-flow.h @@ -264,6 +264,7 @@ void mf_set_value(const struct mf_field *, const union mf_value *value, struct cls_rule *); void mf_set_flow_value(const struct mf_field *, const union mf_value *value, struct flow *); +bool mf_is_zero(const struct mf_field *, const struct flow *); void mf_get(const struct mf_field *, const struct cls_rule *, union mf_value *value, union mf_value *mask); diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c index f4845f6db..034a6de69 100644 --- a/lib/ofp-parse.c +++ b/lib/ofp-parse.c @@ -755,3 +755,80 @@ parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *fsr, fsr->out_port = fm.out_port; fsr->table_id = fm.table_id; } + +/* 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); + } + } + +exit: + free(copy); + + if (error) { + memset(flow, 0, sizeof *flow); + } + return error; +} diff --git a/lib/ofp-parse.h b/lib/ofp-parse.h index 5a50d9498..3e5e62a60 100644 --- a/lib/ofp-parse.h +++ b/lib/ofp-parse.h @@ -23,6 +23,7 @@ #include #include +struct flow; struct ofpbuf; struct ofputil_flow_mod; struct ofputil_flow_stats_request; @@ -41,4 +42,6 @@ void parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *, void parse_ofp_actions(const char *, struct ofpbuf *actions); +char *parse_ofp_exact_flow(struct flow *, const char *); + #endif /* ofp-parse.h */