+ struct cls_subtable *partition, *next_partition;
+ struct cls_subtable *subtable, *next_subtable;
+ int i;
+
+ for (i = 0; i < cls->n_tries; i++) {
+ trie_destroy(cls->tries[i].root);
+ }
+
+ HMAP_FOR_EACH_SAFE (subtable, next_subtable, hmap_node,
+ &cls->subtables) {
+ destroy_subtable(cls, subtable);
+ }
+ hmap_destroy(&cls->subtables);
+
+ HMAP_FOR_EACH_SAFE (partition, next_partition, hmap_node,
+ &cls->partitions) {
+ hmap_remove(&cls->partitions, &partition->hmap_node);
+ free(partition);
+ }
+ hmap_destroy(&cls->partitions);
+ fat_rwlock_destroy(&cls->rwlock);
+ }
+}
+
+/* We use uint64_t as a set for the fields below. */
+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,
+ const enum mf_field_id *trie_fields,
+ unsigned int n_fields)
+{
+ uint64_t fields = 0;
+ int i, trie;
+
+ for (i = 0, trie = 0; i < n_fields && trie < CLS_MAX_TRIES; i++) {
+ const struct mf_field *field = mf_from_id(trie_fields[i]);
+ if (field->flow_be32ofs < 0 || field->n_bits % 32) {
+ /* Incompatible field. This is the only place where we
+ * enforce these requirements, but the rest of the trie code
+ * depends on the flow_be32ofs to be non-negative and the
+ * field length to be a multiple of 32 bits. */
+ continue;
+ }
+
+ if (fields & (UINT64_C(1) << trie_fields[i])) {
+ /* Duplicate field, there is no need to build more than
+ * one index for any one field. */
+ continue;
+ }
+ fields |= UINT64_C(1) << trie_fields[i];
+
+ if (trie >= cls->n_tries || field != cls->tries[trie].field) {
+ trie_init(cls, trie, field);
+ }
+ trie++;
+ }
+
+ /* Destroy the rest. */
+ for (i = trie; i < cls->n_tries; i++) {
+ trie_init(cls, i, NULL);
+ }
+ cls->n_tries = trie;
+}
+
+static void
+trie_init(struct classifier *cls, int trie_idx,
+ const struct mf_field *field)
+{
+ struct cls_trie *trie = &cls->tries[trie_idx];
+ struct cls_subtable *subtable;
+
+ if (trie_idx < cls->n_tries) {
+ trie_destroy(trie->root);
+ }
+ trie->root = NULL;
+ trie->field = field;
+
+ /* Add existing rules to the trie. */
+ LIST_FOR_EACH (subtable, list_node, &cls->subtables_priority) {
+ unsigned int plen;
+
+ plen = field ? minimask_get_prefix_len(&subtable->mask, field) : 0;
+ /* Initialize subtable's prefix length on this field. */
+ subtable->trie_plen[trie_idx] = plen;
+
+ if (plen) {
+ struct cls_rule *head;