ofp-parse: New function parse_ofp_exact_flow().
authorBen Pfaff <blp@nicira.com>
Fri, 4 May 2012 16:52:37 +0000 (09:52 -0700)
committerBen Pfaff <blp@nicira.com>
Mon, 7 May 2012 18:23:31 +0000 (11:23 -0700)
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 <blp@nicira.com>
lib/meta-flow.c
lib/meta-flow.h
lib/ofp-parse.c
lib/ofp-parse.h

index c1efbe2..8b60b35 100644 (file)
@@ -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
index 662778c..632cb46 100644 (file)
@@ -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);
index f4845f6..034a6de 100644 (file)
@@ -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;
+}
index 5a50d94..3e5e62a 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdint.h>
 #include <stdio.h>
 
+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 */