The new function mimics the semantics of 'hmap''s hmap_at_position().
It can be used to iterate through the classifier's rules when locking can't
be used

Signed-off-by: Daniele Di Proietto <ddiproie...@vmware.com>
---
 lib/classifier.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/classifier.h |  6 ++++
 2 files changed, 101 insertions(+)

diff --git a/lib/classifier.c b/lib/classifier.c
index 00d47ac..c3b6877 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -1125,6 +1125,101 @@ classifier_lookup(const struct classifier *cls_, const 
struct flow *flow,
     return best ? best->cls_rule : NULL;
 }
 
+static struct cls_match *
+prio_list_at_position(struct cls_match * match, uint32_t *pri_offsetp)
+{
+    uint32_t pri_offset = *pri_offsetp,
+             i;
+
+    for (i = 0; match; i++, match = next_rule_in_list(match)) {
+        if (i == pri_offset) {
+            if (next_rule_in_list(match)) {
+                *pri_offsetp = pri_offset + 1;
+            } else {
+                *pri_offsetp = 0;
+            }
+
+            return match;
+        }
+    }
+
+    *pri_offsetp = 0;
+    return NULL;
+}
+
+/* Returns the next rule in 'cls_' in hash and list order, or NULL if no rules
+ * remain in 'cls_'. Uses '*bucketp's and '*offsetp's to determine where to
+ * begin iteration, and stores new values to pass on the next iteration
+ * into them before returning.
+ *
+ * It's better to use 'cls_cursor' and related functions, since they are
+ * faster.
+ *
+ * Before beginning iteration, store 0 into '*bucketp's and '*offsetp's.
+ */
+struct cls_rule *
+classifier_at_position(const struct classifier *cls_,
+                       uint32_t *subtbl_bucketp, uint32_t *subtbl_offsetp,
+                       uint32_t *match_bucketp, uint32_t *match_offsetp,
+                       uint32_t *pri_offsetp)
+{
+    struct cls_classifier *cls = cls_->cls;
+
+    for (;;) {
+        struct hmap_node *subtbl_node,
+                         *match_first_node;
+        struct cls_subtable *subtbl;
+        struct cls_match *first_match,
+                         *match;
+        uint32_t match_bucket = *match_bucketp,
+                 match_offset = *match_offsetp,
+                 subtbl_bucket = *subtbl_bucketp,
+                 subtbl_offset = *subtbl_offsetp;
+
+        subtbl_node = hmap_at_position(&cls->subtables_map, &subtbl_bucket,
+                                       &subtbl_offset);
+
+        if (!subtbl_node) {
+            return NULL;
+        }
+
+        subtbl = CONTAINER_OF(subtbl_node, struct cls_subtable, hmap_node);
+
+        match_first_node = hmap_at_position(&subtbl->rules, &match_bucket,
+                                            &match_offset);
+
+        if (!match_first_node) {
+            *subtbl_bucketp = subtbl_bucket;
+            *subtbl_offsetp = subtbl_offset;
+            *match_bucketp = 0;
+            *match_offsetp = 0;
+            *pri_offsetp = 0;
+            continue;
+        }
+
+        first_match = CONTAINER_OF(match_first_node, struct cls_match, 
hmap_node);
+
+        match = prio_list_at_position(first_match, pri_offsetp);
+
+        if (match_bucket == 0 && match_offset == 0) {
+            *subtbl_bucketp = subtbl_bucket;
+            *subtbl_offsetp = subtbl_offset;
+        }
+
+        if (*pri_offsetp == 0) {
+            *match_bucketp = match_bucket;
+            *match_offsetp = match_offset;
+        }
+
+        if (!match) {
+            continue;
+        }
+
+
+        return match->cls_rule;
+    }
+}
+
 /* Returns true if 'target' satisifies 'match', that is, if each bit for which
  * 'match' specifies a particular value has the correct value in 'target'.
  *
diff --git a/lib/classifier.h b/lib/classifier.h
index a89c562..5d98d36 100644
--- a/lib/classifier.h
+++ b/lib/classifier.h
@@ -339,6 +339,12 @@ struct cls_rule *cls_cursor_next(struct cls_cursor *, 
const struct cls_rule *);
           : 0);                                                         \
          (RULE) = (NEXT))
 
+struct cls_rule *
+classifier_at_position(const struct classifier *cls_,
+                       uint32_t *subtbl_bucketp, uint32_t *subtbl_offsetp,
+                       uint32_t *match_bucketp, uint32_t *match_offsetp,
+                       uint32_t *pri_offset);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.0.0.rc0

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to