So it seems to me that the only data needed in struct classifier by
callers is the fat_rwlock.  What if we add a classifier_rdlock() and a
classifier_wrlock() function.  That done, we could entirely hide
struct classifier, and would need to make the distinction between it
and the cls_classifier.  Thoughts?

Ethan

On Fri, Apr 18, 2014 at 12:41 PM, Jarno Rajahalme <jrajaha...@nicira.com> wrote:
> It is better not to expose definitions not needed by users.
>
> Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
> ---
>  lib/classifier.c        |  134 
> ++++++++++++++++++++++++++++++++++++-----------
>  lib/classifier.h        |   65 ++++-------------------
>  tests/test-classifier.c |    6 +--
>  3 files changed, 115 insertions(+), 90 deletions(-)
>
> diff --git a/lib/classifier.c b/lib/classifier.c
> index 8ab1f9c..e48f0a1 100644
> --- a/lib/classifier.c
> +++ b/lib/classifier.c
> @@ -30,18 +30,70 @@
>
>  VLOG_DEFINE_THIS_MODULE(classifier);
>
> +struct trie_node;
> +
> +/* Prefix trie for a 'field' */
> +struct cls_trie {
> +    const struct mf_field *field; /* Trie field, or NULL. */
> +    struct trie_node *root;       /* NULL if none. */
> +};
> +
> +struct cls_classifier {
> +    int n_rules;                /* Total number of rules. */
> +    uint8_t n_flow_segments;
> +    uint8_t flow_segments[CLS_MAX_INDICES]; /* Flow segment boundaries to use
> +                                             * for staged lookup. */
> +    struct hmap subtables;      /* Contains "struct cls_subtable"s.  */
> +    struct list subtables_priority; /* Subtables in descending priority 
> order.
> +                                     */
> +    struct hmap partitions;     /* Contains "struct cls_partition"s. */
> +    struct cls_trie tries[CLS_MAX_TRIES]; /* Prefix tries. */
> +    unsigned int n_tries;
> +};
> +
> +/* A set of rules that all have the same fields wildcarded. */
> +struct cls_subtable {
> +    struct hmap_node hmap_node; /* Within struct cls_classifier 'subtables'
> +                                 * hmap. */
> +    struct list list_node;      /* Within classifier 'subtables_priority' 
> list.
> +                                 */
> +    struct hmap rules;          /* Contains "struct cls_rule"s. */
> +    struct minimask mask;       /* Wildcards for fields. */
> +    int n_rules;                /* Number of rules, including duplicates. */
> +    unsigned int max_priority;  /* Max priority of any rule in the subtable. 
> */
> +    unsigned int max_count;     /* Count of max_priority rules. */
> +    tag_type tag;               /* Tag generated from mask for partitioning. 
> */
> +    uint8_t n_indices;           /* How many indices to use. */
> +    uint8_t index_ofs[CLS_MAX_INDICES]; /* u32 flow segment boundaries. */
> +    struct hindex indices[CLS_MAX_INDICES]; /* Staged lookup indices. */
> +    unsigned int trie_plen[CLS_MAX_TRIES];  /* Trie prefix length in 'mask'. 
> */
> +};
> +
> +/* Associates a metadata value (that is, a value of the OpenFlow 1.1+ 
> metadata
> + * field) with tags for the "cls_subtable"s that contain rules that match 
> that
> + * metadata value.  */
> +struct cls_partition {
> +    struct hmap_node hmap_node; /* In struct cls_classifier's 'partitions'
> +                                 * hmap. */
> +    ovs_be64 metadata;          /* metadata value for this partition. */
> +    tag_type tags;              /* OR of each flow's cls_subtable tag. */
> +    struct tag_tracker tracker; /* Tracks the bits in 'tags'. */
> +};
> +
> +
> +
>  struct trie_ctx;
> -static struct cls_subtable *find_subtable(const struct classifier *,
> +static struct cls_subtable *find_subtable(const struct cls_classifier *,
>                                            const struct minimask *);
> -static struct cls_subtable *insert_subtable(struct classifier *,
> +static struct cls_subtable *insert_subtable(struct cls_classifier *,
>                                              const struct minimask *);
>
> -static void destroy_subtable(struct classifier *, struct cls_subtable *);
> +static void destroy_subtable(struct cls_classifier *, struct cls_subtable *);
>
> -static void update_subtables_after_insertion(struct classifier *,
> +static void update_subtables_after_insertion(struct cls_classifier *,
>                                               struct cls_subtable *,
>                                               unsigned int new_priority);
> -static void update_subtables_after_removal(struct classifier *,
> +static void update_subtables_after_removal(struct cls_classifier *,
>                                             struct cls_subtable *,
>                                             unsigned int del_priority);
>
> @@ -51,7 +103,7 @@ static struct cls_rule *find_match_wc(const struct 
> cls_subtable *,
>                                        struct flow_wildcards *);
>  static struct cls_rule *find_equal(struct cls_subtable *,
>                                     const struct miniflow *, uint32_t hash);
> -static struct cls_rule *insert_rule(struct classifier *,
> +static struct cls_rule *insert_rule(struct cls_classifier *,
>                                      struct cls_subtable *, struct cls_rule 
> *);
>
>  /* Iterates RULE over HEAD and all of the cls_rules on HEAD->list. */
> @@ -67,7 +119,7 @@ static struct cls_rule *next_rule_in_list(struct cls_rule 
> *);
>
>  static unsigned int minimask_get_prefix_len(const struct minimask *,
>                                              const struct mf_field *);
> -static void trie_init(struct classifier *, int trie_idx,
> +static void trie_init(struct cls_classifier *, int trie_idx,
>                        const struct mf_field *);
>  static unsigned int trie_lookup(const struct cls_trie *, const struct flow *,
>                                  unsigned int *checkbits);
> @@ -349,13 +401,18 @@ cls_rule_is_catchall(const struct cls_rule *rule)
>  /* Initializes 'cls' as a classifier that initially contains no 
> classification
>   * rules. */
>  void
> -classifier_init(struct classifier *cls, const uint8_t *flow_segments)
> +classifier_init(struct classifier *cls_, const uint8_t *flow_segments)
>  {
> +    struct cls_classifier *cls = xmalloc(sizeof *cls);
> +
> +    fat_rwlock_init(&cls_->rwlock);
> +
> +    cls_->cls = cls;
> +
>      cls->n_rules = 0;
>      hmap_init(&cls->subtables);
>      list_init(&cls->subtables_priority);
>      hmap_init(&cls->partitions);
> -    fat_rwlock_init(&cls->rwlock);
>      cls->n_flow_segments = 0;
>      if (flow_segments) {
>          while (cls->n_flow_segments < CLS_MAX_INDICES
> @@ -369,13 +426,19 @@ classifier_init(struct classifier *cls, const uint8_t 
> *flow_segments)
>  /* Destroys 'cls'.  Rules within 'cls', if any, are not freed; this is the
>   * caller's responsibility. */
>  void
> -classifier_destroy(struct classifier *cls)
> +classifier_destroy(struct classifier *cls_)
>  {
> -    if (cls) {
> +    if (cls_) {
> +        struct cls_classifier *cls = cls_->cls;
>          struct cls_subtable *partition, *next_partition;
>          struct cls_subtable *subtable, *next_subtable;
>          int i;
>
> +        fat_rwlock_destroy(&cls_->rwlock);
> +        if (!cls) {
> +            return;
> +        }
> +
>          for (i = 0; i < cls->n_tries; i++) {
>              trie_destroy(cls->tries[i].root);
>          }
> @@ -392,7 +455,8 @@ classifier_destroy(struct classifier *cls)
>              free(partition);
>          }
>          hmap_destroy(&cls->partitions);
> -        fat_rwlock_destroy(&cls->rwlock);
> +
> +        free(cls);
>      }
>  }
>
> @@ -401,10 +465,11 @@ BUILD_ASSERT_DECL(MFF_N_IDS <= 64);
>
>  /* Set the fields for which prefix lookup should be performed. */
>  void
> -classifier_set_prefix_fields(struct classifier *cls,
> +classifier_set_prefix_fields(struct classifier *cls_,
>                               const enum mf_field_id *trie_fields,
>                               unsigned int n_fields)
>  {
> +    struct cls_classifier *cls = cls_->cls;
>      uint64_t fields = 0;
>      int i, trie;
>
> @@ -439,7 +504,7 @@ classifier_set_prefix_fields(struct classifier *cls,
>  }
>
>  static void
> -trie_init(struct classifier *cls, int trie_idx,
> +trie_init(struct cls_classifier *cls, int trie_idx,
>            const struct mf_field *field)
>  {
>      struct cls_trie *trie = &cls->tries[trie_idx];
> @@ -477,14 +542,14 @@ trie_init(struct classifier *cls, int trie_idx,
>  bool
>  classifier_is_empty(const struct classifier *cls)
>  {
> -    return cls->n_rules == 0;
> +    return cls->cls->n_rules == 0;
>  }
>
>  /* Returns the number of rules in 'cls'. */
>  int
>  classifier_count(const struct classifier *cls)
>  {
> -    return cls->n_rules;
> +    return cls->cls->n_rules;
>  }
>
>  static uint32_t
> @@ -495,7 +560,8 @@ hash_metadata(ovs_be64 metadata_)
>  }
>
>  static struct cls_partition *
> -find_partition(const struct classifier *cls, ovs_be64 metadata, uint32_t 
> hash)
> +find_partition(const struct cls_classifier *cls, ovs_be64 metadata,
> +               uint32_t hash)
>  {
>      struct cls_partition *partition;
>
> @@ -509,7 +575,7 @@ find_partition(const struct classifier *cls, ovs_be64 
> metadata, uint32_t hash)
>  }
>
>  static struct cls_partition *
> -create_partition(struct classifier *cls, struct cls_subtable *subtable,
> +create_partition(struct cls_classifier *cls, struct cls_subtable *subtable,
>                   ovs_be64 metadata)
>  {
>      uint32_t hash = hash_metadata(metadata);
> @@ -539,8 +605,9 @@ create_partition(struct classifier *cls, struct 
> cls_subtable *subtable,
>   * rule, even rules that cannot have any effect because the new rule matches 
> a
>   * superset of their flows and has higher priority. */
>  struct cls_rule *
> -classifier_replace(struct classifier *cls, struct cls_rule *rule)
> +classifier_replace(struct classifier *cls_, struct cls_rule *rule)
>  {
> +    struct cls_classifier *cls = cls_->cls;
>      struct cls_rule *old_rule;
>      struct cls_subtable *subtable;
>
> @@ -591,8 +658,9 @@ classifier_insert(struct classifier *cls, struct cls_rule 
> *rule)
>   * 'rule' with cls_rule_destroy(), freeing the memory block in which 'rule'
>   * resides, etc., as necessary. */
>  void
> -classifier_remove(struct classifier *cls, struct cls_rule *rule)
> +classifier_remove(struct classifier *cls_, struct cls_rule *rule)
>  {
> +    struct cls_classifier *cls = cls_->cls;
>      struct cls_partition *partition;
>      struct cls_rule *head;
>      struct cls_subtable *subtable;
> @@ -672,9 +740,10 @@ trie_ctx_init(struct trie_ctx *ctx, const struct 
> cls_trie *trie)
>   * earlier, 'wc' should have been initialized (e.g., by
>   * flow_wildcards_init_catchall()). */
>  struct cls_rule *
> -classifier_lookup(const struct classifier *cls, const struct flow *flow,
> +classifier_lookup(const struct classifier *cls_, const struct flow *flow,
>                    struct flow_wildcards *wc)
>  {
> +    struct cls_classifier *cls = cls_->cls;
>      const struct cls_partition *partition;
>      struct cls_subtable *subtable;
>      struct cls_rule *best;
> @@ -787,9 +856,10 @@ find_match_miniflow(const struct cls_subtable *subtable,
>   * This function is optimized for the userspace datapath, which only ever has
>   * one priority value for it's flows!
>   */
> -struct cls_rule *classifier_lookup_miniflow_first(const struct classifier 
> *cls,
> +struct cls_rule *classifier_lookup_miniflow_first(const struct classifier 
> *cls_,
>                                                    const struct miniflow 
> *flow)
>  {
> +    struct cls_classifier *cls = cls_->cls;
>      struct cls_subtable *subtable;
>
>      LIST_FOR_EACH (subtable, list_node, &cls->subtables_priority) {
> @@ -811,9 +881,10 @@ struct cls_rule *classifier_lookup_miniflow_first(const 
> struct classifier *cls,
>   * matching criteria as 'target'.  Returns a null pointer if 'cls' doesn't
>   * contain an exact match. */
>  struct cls_rule *
> -classifier_find_rule_exactly(const struct classifier *cls,
> +classifier_find_rule_exactly(const struct classifier *cls_,
>                               const struct cls_rule *target)
>  {
> +    struct cls_classifier *cls = cls_->cls;
>      struct cls_rule *head, *rule;
>      struct cls_subtable *subtable;
>
> @@ -860,9 +931,10 @@ classifier_find_match_exactly(const struct classifier 
> *cls,
>   * considered to overlap if both rules have the same priority and a packet
>   * could match both. */
>  bool
> -classifier_rule_overlaps(const struct classifier *cls,
> +classifier_rule_overlaps(const struct classifier *cls_,
>                           const struct cls_rule *target)
>  {
> +    struct cls_classifier *cls = cls_->cls;
>      struct cls_subtable *subtable;
>
>      /* Iterate subtables in the descending max priority order. */
> @@ -976,7 +1048,7 @@ void
>  cls_cursor_init(struct cls_cursor *cursor, const struct classifier *cls,
>                  const struct cls_rule *target)
>  {
> -    cursor->cls = cls;
> +    cursor->cls = cls->cls;
>      cursor->target = target && !cls_rule_is_catchall(target) ? target : NULL;
>  }
>
> @@ -1035,7 +1107,7 @@ cls_cursor_next(struct cls_cursor *cursor, const struct 
> cls_rule *rule_)
>  }
>
>  static struct cls_subtable *
> -find_subtable(const struct classifier *cls, const struct minimask *mask)
> +find_subtable(const struct cls_classifier *cls, const struct minimask *mask)
>  {
>      struct cls_subtable *subtable;
>
> @@ -1049,7 +1121,7 @@ find_subtable(const struct classifier *cls, const 
> struct minimask *mask)
>  }
>
>  static struct cls_subtable *
> -insert_subtable(struct classifier *cls, const struct minimask *mask)
> +insert_subtable(struct cls_classifier *cls, const struct minimask *mask)
>  {
>      uint32_t hash = minimask_hash(mask, 0);
>      struct cls_subtable *subtable;
> @@ -1104,7 +1176,7 @@ insert_subtable(struct classifier *cls, const struct 
> minimask *mask)
>  }
>
>  static void
> -destroy_subtable(struct classifier *cls, struct cls_subtable *subtable)
> +destroy_subtable(struct cls_classifier *cls, struct cls_subtable *subtable)
>  {
>      int i;
>
> @@ -1129,7 +1201,7 @@ destroy_subtable(struct classifier *cls, struct 
> cls_subtable *subtable)
>   * This function should only be called after adding a new rule, not after
>   * replacing a rule by an identical one or modifying a rule in-place. */
>  static void
> -update_subtables_after_insertion(struct classifier *cls,
> +update_subtables_after_insertion(struct cls_classifier *cls,
>                                   struct cls_subtable *subtable,
>                                   unsigned int new_priority)
>  {
> @@ -1173,7 +1245,7 @@ update_subtables_after_insertion(struct classifier *cls,
>   * This function should only be called after removing a rule, not after
>   * replacing a rule by an identical one or modifying a rule in-place. */
>  static void
> -update_subtables_after_removal(struct classifier *cls,
> +update_subtables_after_removal(struct cls_classifier *cls,
>                                 struct cls_subtable *subtable,
>                                 unsigned int del_priority)
>  {
> @@ -1390,7 +1462,7 @@ find_equal(struct cls_subtable *subtable, const struct 
> miniflow *flow,
>  }
>
>  static struct cls_rule *
> -insert_rule(struct classifier *cls, struct cls_subtable *subtable,
> +insert_rule(struct cls_classifier *cls, struct cls_subtable *subtable,
>              struct cls_rule *new)
>  {
>      struct cls_rule *head;
> diff --git a/lib/classifier.h b/lib/classifier.h
> index 9022fab..048aaa1 100644
> --- a/lib/classifier.h
> +++ b/lib/classifier.h
> @@ -232,60 +232,23 @@ extern "C" {
>
>  /* Needed only for the lock annotation in struct classifier. */
>  extern struct ovs_mutex ofproto_mutex;
> -struct trie_node;
>
> -/* Prefix trie for a 'field' */
> -struct cls_trie {
> -    const struct mf_field *field; /* Trie field, or NULL. */
> -    struct trie_node *root;       /* NULL if none. */
> -};
> -
> -enum {
> -    CLS_MAX_INDICES = 3, /* Maximum number of lookup indices per subtable. */
> -    CLS_MAX_TRIES = 3    /* Maximum number of prefix trees per classifier. */
> -};
> +/* Classifier internal data structures. */
> +struct cls_classifier;
> +struct cls_subtable;
> +struct cls_partition;
>
>  /* A flow classifier. */
>  struct classifier {
> -    int n_rules;                /* Total number of rules. */
> -    uint8_t n_flow_segments;
> -    uint8_t flow_segments[CLS_MAX_INDICES]; /* Flow segment boundaries to use
> -                                             * for staged lookup. */
> -    struct hmap subtables;      /* Contains "struct cls_subtable"s.  */
> -    struct list subtables_priority; /* Subtables in descending priority 
> order.
> -                                     */
> -    struct hmap partitions;     /* Contains "struct cls_partition"s. */
>      struct fat_rwlock rwlock OVS_ACQ_AFTER(ofproto_mutex);
> -    struct cls_trie tries[CLS_MAX_TRIES]; /* Prefix tries. */
> -    unsigned int n_tries;
> +    struct cls_classifier *cls;
>  };
>
> -/* A set of rules that all have the same fields wildcarded. */
> -struct cls_subtable {
> -    struct hmap_node hmap_node; /* Within struct classifier 'subtables' hmap.
> -                                 */
> -    struct list list_node;      /* Within classifier 'subtables_priority' 
> list.
> -                                 */
> -    struct hmap rules;          /* Contains "struct cls_rule"s. */
> -    struct minimask mask;       /* Wildcards for fields. */
> -    int n_rules;                /* Number of rules, including duplicates. */
> -    unsigned int max_priority;  /* Max priority of any rule in the subtable. 
> */
> -    unsigned int max_count;     /* Count of max_priority rules. */
> -    tag_type tag;               /* Tag generated from mask for partitioning. 
> */
> -    uint8_t n_indices;           /* How many indices to use. */
> -    uint8_t index_ofs[CLS_MAX_INDICES]; /* u32 flow segment boundaries. */
> -    struct hindex indices[CLS_MAX_INDICES]; /* Staged lookup indices. */
> -    unsigned int trie_plen[CLS_MAX_TRIES];  /* Trie prefix length in 'mask'. 
> */
> +enum {
> +    CLS_MAX_INDICES = 3, /* Maximum number of lookup indices per subtable. */
> +    CLS_MAX_TRIES = 3    /* Maximum number of prefix trees per classifier. */
>  };
>
> -/* Returns true if 'table' is a "catch-all" subtable that will match every
> - * packet (if there is no higher-priority match). */
> -static inline bool
> -cls_subtable_is_catchall(const struct cls_subtable *subtable)
> -{
> -    return minimask_is_catchall(&subtable->mask);
> -}
> -
>  /* A rule in a "struct cls_subtable". */
>  struct cls_rule {
>      struct hmap_node hmap_node; /* Within struct cls_subtable 'rules'. */
> @@ -297,16 +260,6 @@ struct cls_rule {
>                                                        * 'indices'. */
>  };
>
> -/* Associates a metadata value (that is, a value of the OpenFlow 1.1+ 
> metadata
> - * field) with tags for the "cls_subtable"s that contain rules that match 
> that
> - * metadata value.  */
> -struct cls_partition {
> -    struct hmap_node hmap_node; /* In struct classifier's 'partitions' hmap. 
> */
> -    ovs_be64 metadata;          /* metadata value for this partition. */
> -    tag_type tags;              /* OR of each flow's cls_subtable tag. */
> -    struct tag_tracker tracker; /* Tracks the bits in 'tags'. */
> -};
> -
>  void cls_rule_init(struct cls_rule *, const struct match *,
>                     unsigned int priority);
>  void cls_rule_init_from_minimatch(struct cls_rule *, const struct minimatch 
> *,
> @@ -366,7 +319,7 @@ struct cls_rule *classifier_find_match_exactly(const 
> struct classifier *cls,
>  /* Iteration. */
>
>  struct cls_cursor {
> -    const struct classifier *cls;
> +    const struct cls_classifier *cls;
>      const struct cls_subtable *subtable;
>      const struct cls_rule *target;
>  };
> diff --git a/tests/test-classifier.c b/tests/test-classifier.c
> index 48eb8de..84f9367 100644
> --- a/tests/test-classifier.c
> +++ b/tests/test-classifier.c
> @@ -475,7 +475,7 @@ check_tables(const struct classifier *cls, int n_tables, 
> int n_rules,
>      int found_dups = 0;
>      int found_rules2 = 0;
>
> -    HMAP_FOR_EACH (table, hmap_node, &cls->subtables) {
> +    HMAP_FOR_EACH (table, hmap_node, &cls->cls->subtables) {
>          const struct cls_rule *head;
>          unsigned int max_priority = 0;
>          unsigned int max_count = 0;
> @@ -509,8 +509,8 @@ check_tables(const struct classifier *cls, int n_tables, 
> int n_rules,
>          assert(table->max_count == max_count);
>      }
>
> -    assert(found_tables == hmap_count(&cls->subtables));
> -    assert(n_tables == -1 || n_tables == hmap_count(&cls->subtables));
> +    assert(found_tables == hmap_count(&cls->cls->subtables));
> +    assert(n_tables == -1 || n_tables == hmap_count(&cls->cls->subtables));
>      assert(n_rules == -1 || found_rules == n_rules);
>      assert(n_dups == -1 || found_dups == n_dups);
>
> --
> 1.7.10.4
>
> _______________________________________________
> dev mailing list
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to