I assume that's the only change. If so, it sounds good. I hope we can catch
the bug quickly.
On May 11, 2014 8:34 PM, "Jarno Rajahalme" <jrajaha...@nicira.com> wrote:

> Assert failures that should not happen have been reported on some
> (non-OVS) test cases.  This patch adds diagnostics to analyze what
> goes wrong.
>
> None of the OVS unit tests trigger these, so there is no performance
> penalty.
>
> This could be moved to test-classifier once it has served it's
> purpose.
>
> Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
> ---
> v2: abort() after dignostics so this will be harder to dismiss.
>
>  lib/classifier.c |  134
> +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 132 insertions(+), 2 deletions(-)
>
> diff --git a/lib/classifier.c b/lib/classifier.c
> index 2646996..a9046cd 100644
> --- a/lib/classifier.c
> +++ b/lib/classifier.c
> @@ -262,6 +262,126 @@ cls_subtable_cache_remove(struct cls_subtable_cache
> *array,
>           ITER > (ARRAY)->subtables                                  \
>               && OVS_LIKELY(SUBTABLE = (--ITER)->subtable);)
>
> +static void
> +cls_subtable_cache_verify(struct cls_subtable_cache *array)
> +{
> +    struct cls_subtable *table;
> +    struct cls_subtable_entry *iter;
> +    unsigned int priority = 0;
> +
> +    CLS_SUBTABLE_CACHE_FOR_EACH_REVERSE (table, iter, array) {
> +        if (iter->max_priority != table->max_priority) {
> +            VLOG_WARN("Subtable %p has mismatching priority in cache (%u
> != %u)",
> +                      table, iter->max_priority, table->max_priority);
> +        }
> +        if (iter->max_priority < priority) {
> +            VLOG_WARN("Subtable cache is out of order (%u < %u)",
> +                      iter->max_priority, priority);
> +        }
> +        priority = iter->max_priority;
> +    }
> +}
> +
> +static void
> +cls_subtable_cache_reset(struct cls_classifier *cls)
> +{
> +    struct cls_subtable_cache old = cls->subtables_priority;
> +    struct cls_subtable *subtable;
> +
> +    VLOG_WARN("Resetting subtable cache.");
> +
> +    cls_subtable_cache_verify(&cls->subtables_priority);
> +
> +    cls_subtable_cache_init(&cls->subtables_priority);
> +
> +    HMAP_FOR_EACH (subtable, hmap_node, &cls->subtables) {
> +        struct cls_match *head;
> +        struct cls_subtable_entry elem;
> +        struct cls_subtable *table;
> +        struct cls_subtable_entry *iter, *subtable_iter = NULL;
> +        unsigned int new_max = 0;
> +        unsigned int max_count = 0;
> +        bool found;
> +
> +        /* Verify max_priority. */
> +        HMAP_FOR_EACH (head, hmap_node, &subtable->rules) {
> +            if (head->priority > new_max) {
> +                new_max = head->priority;
> +                max_count = 1;
> +            } else if (head->priority == new_max) {
> +                max_count++;
> +            }
> +        }
> +        if (new_max != subtable->max_priority ||
> +            max_count != subtable->max_count) {
> +            VLOG_WARN("subtable %p (%u rules) has mismatching
> max_priority "
> +                      "(%u) or max_count (%u). Highest priority found was
> %u, "
> +                      "count: %u",
> +                      subtable, subtable->n_rules, subtable->max_priority,
> +                      subtable->max_count, new_max, max_count);
> +            subtable->max_priority = new_max;
> +            subtable->max_count = max_count;
> +        }
> +
> +        /* Locate the subtable from the old cache. */
> +        found = false;
> +        CLS_SUBTABLE_CACHE_FOR_EACH (table, iter, &old) {
> +            if (table == subtable) {
> +                if (iter->max_priority != new_max) {
> +                    VLOG_WARN("Subtable %p has wrong max priority (%u !=
> %u) "
> +                              "in the old cache.",
> +                              subtable, iter->max_priority, new_max);
> +                }
> +                if (found) {
> +                    VLOG_WARN("Subtable %p duplicated in the old cache.",
> +                              subtable);
> +                }
> +                found = true;
> +            }
> +        }
> +        if (!found) {
> +            VLOG_WARN("Subtable %p not found from the old cache.",
> subtable);
> +        }
> +
> +        elem.subtable = subtable;
> +        elem.tag = subtable->tag;
> +        elem.max_priority = subtable->max_priority;
> +        cls_subtable_cache_push_back(&cls->subtables_priority, elem);
> +
> +        /* Possibly move 'subtable' earlier in the priority list.  If we
> break
> +         * out of the loop, then 'subtable_iter' should be moved just
> before
> +         * 'iter'.  If the loop terminates normally, then 'iter' will be
> the
> +         * first list element and we'll move subtable just before that
> +         * (e.g. to the front of the list). */
> +        CLS_SUBTABLE_CACHE_FOR_EACH_REVERSE (table, iter,
> +                                             &cls->subtables_priority) {
> +            if (table == subtable) {
> +                subtable_iter = iter; /* Locate the subtable as we go. */
> +            } else if (table->max_priority >= new_max) {
> +                ovs_assert(subtable_iter != NULL);
> +                iter++;
> +                break;
> +            }
> +        }
> +
> +        /* Move 'subtable' just before 'iter' (unless it's already
> there). */
> +        if (iter != subtable_iter) {
> +            cls_subtable_cache_splice(iter, subtable_iter, subtable_iter
> + 1);
> +        }
> +    }
> +
> +    /* Verify that the old and the new have the same size. */
> +    if (old.size != cls->subtables_priority.size) {
> +        VLOG_WARN("subtables cache sizes differ: old (%"PRIuSIZE
> +                  ") != new (%"PRIuSIZE").",
> +                  old.size, cls->subtables_priority.size);
> +    }
> +
> +    cls_subtable_cache_destroy(&old);
> +
> +    cls_subtable_cache_verify(&cls->subtables_priority);
> +}
> +
>
>  /* flow/miniflow/minimask/minimatch utilities.
>   * These are only used by the classifier, so place them here to allow
> @@ -1446,7 +1566,12 @@ update_subtables_after_insertion(struct
> cls_classifier *cls,
>                  subtable_iter = iter; /* Locate the subtable as we go. */
>                  iter->max_priority = new_priority;
>              } else if (table->max_priority >= new_priority) {
> -                ovs_assert(subtable_iter != NULL);
> +                if (subtable_iter == NULL) {
> +                    /* Corrupted cache? */
> +                    cls_subtable_cache_reset(cls);
> +                    VLOG_ABORT("update_subtables_after_insertion():
> Subtable priority list corrupted.");
> +                    OVS_NOT_REACHED();
> +                }
>                  iter++;
>                  break;
>              }
> @@ -1499,7 +1624,12 @@ update_subtables_after_removal(struct
> cls_classifier *cls,
>                  subtable_iter = iter; /* Locate the subtable as we go. */
>                  iter->max_priority = subtable->max_priority;
>              } else if (table->max_priority <= subtable->max_priority) {
> -                ovs_assert(subtable_iter != NULL);
> +                if (subtable_iter == NULL) {
> +                    /* Corrupted cache? */
> +                    cls_subtable_cache_reset(cls);
> +                    VLOG_ABORT("update_subtables_after_removal():
> Subtable priority list corrupted.");
> +                    OVS_NOT_REACHED();
> +                }
>                  break;
>              }
>          }
> --
> 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