diff --git a/SOURCES/openvswitch-2.13.0.patch b/SOURCES/openvswitch-2.13.0.patch
index 5746669..c68b0a9 100644
--- a/SOURCES/openvswitch-2.13.0.patch
+++ b/SOURCES/openvswitch-2.13.0.patch
@@ -785,6 +785,19 @@ index dbf88ec43f..7acdaac06b 100644
  Reporting Bugs
  --------------
  
+diff --git a/Documentation/intro/install/general.rst b/Documentation/intro/install/general.rst
+index 09f2c13f16..6312f5879c 100644
+--- a/Documentation/intro/install/general.rst
++++ b/Documentation/intro/install/general.rst
+@@ -167,7 +167,7 @@ other than plain text, only if you have the following:
+ If you are going to extensively modify Open vSwitch, consider installing the
+ following to obtain better warnings:
+ 
+-- "sparse" version 0.5.1 or later
++- "sparse" version 0.6.2 or later
+   (https://git.kernel.org/pub/scm/devel/sparse/sparse.git/).
+ 
+ - GNU make.
 diff --git a/Documentation/topics/dpdk/phy.rst b/Documentation/topics/dpdk/phy.rst
 index 38e52c8deb..55a98e2b0e 100644
 --- a/Documentation/topics/dpdk/phy.rst
@@ -1535,7 +1548,7 @@ index e06ddf2671..8e64d74aee 100644
      :target: https://ci.appveyor.com/project/blp/ovs/history
  .. image:: https://api.cirrus-ci.com/github/openvswitch/ovs.svg
 diff --git a/acinclude.m4 b/acinclude.m4
-index c1470ccc6b..6401471494 100644
+index c1470ccc6b..106689493f 100644
 --- a/acinclude.m4
 +++ b/acinclude.m4
 @@ -192,10 +192,10 @@ dnl Configure Linux tc compat.
@@ -1645,6 +1658,15 @@ index c1470ccc6b..6401471494 100644
    OVS_FIND_PARAM_IFELSE([$KSRC/include/net/protocol.h],
                          [udp_add_offload], [net],
                          [OVS_DEFINE([HAVE_UDP_ADD_OFFLOAD_TAKES_NET])])
+@@ -1284,7 +1319,7 @@ AC_DEFUN([OVS_ENABLE_SPARSE],
+    : ${SPARSE=sparse}
+    AC_SUBST([SPARSE])
+    AC_CONFIG_COMMANDS_PRE(
+-     [CC='$(if $(C:0=),env REAL_CC="'"$CC"'" CHECK="$(SPARSE) $(SPARSE_WERROR) -I $(top_srcdir)/include/sparse $(SPARSEFLAGS) $(SPARSE_EXTRA_INCLUDES) " cgcc $(CGCCFLAGS),'"$CC"')'])
++     [CC='$(if $(C:0=),env REAL_CC="'"$CC"'" CHECK="$(SPARSE) $(SPARSE_WERROR) -I $(top_srcdir)/include/sparse -I $(top_srcdir)/include $(SPARSEFLAGS) $(SPARSE_EXTRA_INCLUDES) " cgcc $(CGCCFLAGS),'"$CC"')'])
+ 
+    AC_ARG_ENABLE(
+      [sparse],
 @@ -1294,11 +1329,11 @@ AC_DEFUN([OVS_ENABLE_SPARSE],
  
  dnl OVS_CTAGS_IDENTIFIERS
@@ -80868,6 +80890,211 @@ index 5289a70f6e..cf009f8264 100644
  #define OVS_LOCKABLE __attribute__((lockable))
  #define OVS_REQ_RDLOCK(...) __attribute__((shared_locks_required(__VA_ARGS__)))
  #define OVS_ACQ_RDLOCK(...) __attribute__((shared_lock_function(__VA_ARGS__)))
+diff --git a/include/openvswitch/hmap.h b/include/openvswitch/hmap.h
+index 8aea9c22db..68c284cf14 100644
+--- a/include/openvswitch/hmap.h
++++ b/include/openvswitch/hmap.h
+@@ -134,15 +134,17 @@ struct hmap_node *hmap_random_node(const struct hmap *);
+  * without using 'break', NODE will be NULL.  This is true for all of the
+  * HMAP_FOR_EACH_*() macros.
+  */
+-#define HMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HMAP)               \
+-    for (INIT_CONTAINER(NODE, hmap_first_with_hash(HMAP, HASH), MEMBER); \
+-         (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL); \
+-         ASSIGN_CONTAINER(NODE, hmap_next_with_hash(&(NODE)->MEMBER),   \
+-                          MEMBER))
+-#define HMAP_FOR_EACH_IN_BUCKET(NODE, MEMBER, HASH, HMAP)               \
+-    for (INIT_CONTAINER(NODE, hmap_first_in_bucket(HMAP, HASH), MEMBER); \
+-         (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL); \
+-         ASSIGN_CONTAINER(NODE, hmap_next_in_bucket(&(NODE)->MEMBER), MEMBER))
++#define HMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HMAP)                     \
++    for (INIT_MULTIVAR(NODE, MEMBER, hmap_first_with_hash(HMAP, HASH),        \
++                       struct hmap_node);                                     \
++         CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);            \
++         UPDATE_MULTIVAR(NODE, hmap_next_with_hash(ITER_VAR(NODE))))
++
++#define HMAP_FOR_EACH_IN_BUCKET(NODE, MEMBER, HASH, HMAP)                     \
++    for (INIT_MULTIVAR(NODE, MEMBER, hmap_first_in_bucket(HMAP, HASH),        \
++                       struct hmap_node);                                     \
++         CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);            \
++         UPDATE_MULTIVAR(NODE, hmap_next_in_bucket(ITER_VAR(NODE))))
+ 
+ static inline struct hmap_node *hmap_first_with_hash(const struct hmap *,
+                                                      size_t hash);
+@@ -168,50 +170,62 @@ bool hmap_contains(const struct hmap *, const struct hmap_node *);
+ /* Iterates through every node in HMAP. */
+ #define HMAP_FOR_EACH(NODE, MEMBER, HMAP) \
+     HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, (void) 0)
+-#define HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, ...)                     \
+-    for (INIT_CONTAINER(NODE, hmap_first(HMAP), MEMBER), __VA_ARGS__;   \
+-         (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL); \
+-         ASSIGN_CONTAINER(NODE, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER))
++#define HMAP_FOR_EACH_INIT(NODE, MEMBER, HMAP, ...)                           \
++    for (INIT_MULTIVAR_EXP(NODE, MEMBER, hmap_first(HMAP), struct hmap_node,  \
++                           __VA_ARGS__);                                      \
++         CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);            \
++         UPDATE_MULTIVAR(NODE, hmap_next(HMAP, ITER_VAR(NODE))))
+ 
+ /* Safe when NODE may be freed (not needed when NODE may be removed from the
+  * hash map but its members remain accessible and intact). */
+ #define HMAP_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HMAP) \
+-    HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, (void) 0)
+-#define HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, ...)          \
+-    for (INIT_CONTAINER(NODE, hmap_first(HMAP), MEMBER), __VA_ARGS__;   \
+-         ((NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL) \
+-          ? INIT_CONTAINER(NEXT, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER), 1 \
+-          : 0);                                                         \
+-         (NODE) = (NEXT))
++    HMAP_FOR_EACH_SAFE_INIT (NODE, NEXT, MEMBER, HMAP, (void) NEXT)
++
++#define HMAP_FOR_EACH_SAFE_INIT(NODE, NEXT, MEMBER, HMAP, ...)                \
++    for (INIT_MULTIVAR_SAFE_LONG_EXP(NODE, NEXT, MEMBER, hmap_first(HMAP),    \
++                                      struct hmap_node, __VA_ARGS__);         \
++         CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,                     \
++                                      ITER_VAR(NODE) != NULL,                 \
++                            ITER_VAR(NEXT) = hmap_next(HMAP, ITER_VAR(NODE)), \
++                                      ITER_VAR(NEXT) != NULL);                \
++         UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
+ 
+ /* Continues an iteration from just after NODE. */
+ #define HMAP_FOR_EACH_CONTINUE(NODE, MEMBER, HMAP) \
+     HMAP_FOR_EACH_CONTINUE_INIT(NODE, MEMBER, HMAP, (void) 0)
+-#define HMAP_FOR_EACH_CONTINUE_INIT(NODE, MEMBER, HMAP, ...)            \
+-    for (ASSIGN_CONTAINER(NODE, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER), \
+-         __VA_ARGS__;                                                   \
+-         (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL); \
+-         ASSIGN_CONTAINER(NODE, hmap_next(HMAP, &(NODE)->MEMBER), MEMBER))
++#define HMAP_FOR_EACH_CONTINUE_INIT(NODE, MEMBER, HMAP, ...)                  \
++    for (INIT_MULTIVAR_EXP(NODE, MEMBER, hmap_next(HMAP, &(NODE)->MEMBER),    \
++                           struct hmap_node, __VA_ARGS__);                    \
++         CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);            \
++         UPDATE_MULTIVAR(NODE, hmap_next(HMAP, ITER_VAR(NODE))))
++
++struct hmap_pop_helper_iter__ {
++    size_t bucket;
++    struct hmap_node *node;
++};
+ 
+-static inline struct hmap_node *
+-hmap_pop_helper__(struct hmap *hmap, size_t *bucket) {
++static inline void
++hmap_pop_helper__(struct hmap *hmap, struct hmap_pop_helper_iter__ *iter) {
+ 
+-    for (; *bucket <= hmap->mask; (*bucket)++) {
+-        struct hmap_node *node = hmap->buckets[*bucket];
++    for (; iter->bucket <= hmap->mask; (iter->bucket)++) {
++        struct hmap_node *node = hmap->buckets[iter->bucket];
+ 
+         if (node) {
+             hmap_remove(hmap, node);
+-            return node;
++            iter->node = node;
++            return;
+         }
+     }
+-
+-    return NULL;
++    iter->node = NULL;
+ }
+ 
+-#define HMAP_FOR_EACH_POP(NODE, MEMBER, HMAP)                               \
+-    for (size_t bucket__ = 0;                                               \
+-         INIT_CONTAINER(NODE, hmap_pop_helper__(HMAP, &bucket__), MEMBER),  \
+-         (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)) || (NODE = NULL);)
++#define HMAP_FOR_EACH_POP(NODE, MEMBER, HMAP)                                 \
++    for (struct hmap_pop_helper_iter__ ITER_VAR(NODE) = { 0, NULL };          \
++         hmap_pop_helper__(HMAP, &ITER_VAR(NODE)),                            \
++         (ITER_VAR(NODE).node != NULL) ?                                      \
++            (((NODE) = OBJECT_CONTAINING(ITER_VAR(NODE).node,                 \
++                                         NODE, MEMBER)),1):                   \
++            (((NODE) = NULL), 0);)
+ 
+ static inline struct hmap_node *hmap_first(const struct hmap *);
+ static inline struct hmap_node *hmap_next(const struct hmap *,
+diff --git a/include/openvswitch/list.h b/include/openvswitch/list.h
+index 8ad5eeb327..bbd2edbd0c 100644
+--- a/include/openvswitch/list.h
++++ b/include/openvswitch/list.h
+@@ -72,37 +72,48 @@ static inline bool ovs_list_is_empty(const struct ovs_list *);
+ static inline bool ovs_list_is_singleton(const struct ovs_list *);
+ static inline bool ovs_list_is_short(const struct ovs_list *);
+ 
+-#define LIST_FOR_EACH(ITER, MEMBER, LIST)                               \
+-    for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER);                    \
+-         &(ITER)->MEMBER != (LIST);                                     \
+-         ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER))
+-#define LIST_FOR_EACH_CONTINUE(ITER, MEMBER, LIST)                      \
+-    for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER);             \
+-         &(ITER)->MEMBER != (LIST);                                     \
+-         ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.next, MEMBER))
+-#define LIST_FOR_EACH_REVERSE(ITER, MEMBER, LIST)                       \
+-    for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER);                    \
+-         &(ITER)->MEMBER != (LIST);                                     \
+-         ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
+-#define LIST_FOR_EACH_REVERSE_SAFE(ITER, PREV, MEMBER, LIST)        \
+-    for (INIT_CONTAINER(ITER, (LIST)->prev, MEMBER);                \
+-         (&(ITER)->MEMBER != (LIST)                                 \
+-          ? INIT_CONTAINER(PREV, (ITER)->MEMBER.prev, MEMBER), 1    \
+-          : 0);                                                     \
+-         (ITER) = (PREV))
+-#define LIST_FOR_EACH_REVERSE_CONTINUE(ITER, MEMBER, LIST)              \
+-    for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER);           \
+-         &(ITER)->MEMBER != (LIST);                                     \
+-         ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
+-#define LIST_FOR_EACH_SAFE(ITER, NEXT, MEMBER, LIST)               \
+-    for (INIT_CONTAINER(ITER, (LIST)->next, MEMBER);               \
+-         (&(ITER)->MEMBER != (LIST)                                \
+-          ? INIT_CONTAINER(NEXT, (ITER)->MEMBER.next, MEMBER), 1   \
+-          : 0);                                                    \
+-         (ITER) = (NEXT))
+-#define LIST_FOR_EACH_POP(ITER, MEMBER, LIST)                      \
+-    while (!ovs_list_is_empty(LIST)                                    \
+-           && (INIT_CONTAINER(ITER, ovs_list_pop_front(LIST), MEMBER), 1))
++#define LIST_FOR_EACH(VAR, MEMBER, LIST)                                      \
++    for (INIT_MULTIVAR(VAR, MEMBER, (LIST)->next, struct ovs_list);           \
++         CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));            \
++         UPDATE_MULTIVAR(VAR, ITER_VAR(VAR)->next))
++
++#define LIST_FOR_EACH_CONTINUE(VAR, MEMBER, LIST)                             \
++    for (INIT_MULTIVAR(VAR, MEMBER, VAR->MEMBER.next, struct ovs_list);       \
++         CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));            \
++         UPDATE_MULTIVAR(VAR, ITER_VAR(VAR)->next))
++
++#define LIST_FOR_EACH_REVERSE(VAR, MEMBER, LIST)                              \
++    for (INIT_MULTIVAR(VAR, MEMBER, (LIST)->prev, struct ovs_list);           \
++         CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));            \
++         UPDATE_MULTIVAR(VAR, ITER_VAR(VAR)->prev))
++
++#define LIST_FOR_EACH_REVERSE_CONTINUE(VAR, MEMBER, LIST)                     \
++    for (INIT_MULTIVAR(VAR, MEMBER, VAR->MEMBER.prev, struct ovs_list);       \
++         CONDITION_MULTIVAR(VAR, MEMBER, ITER_VAR(VAR) != (LIST));            \
++         UPDATE_MULTIVAR(VAR, ITER_VAR(VAR)->prev))
++
++#define LIST_FOR_EACH_REVERSE_SAFE(VAR, PREV, MEMBER, LIST)                   \
++    for (INIT_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER, (LIST)->prev,             \
++                                 struct ovs_list);                            \
++         CONDITION_MULTIVAR_SAFE_LONG(VAR, PREV, MEMBER,                      \
++                                      ITER_VAR(VAR) != (LIST),                \
++                                      ITER_VAR(PREV) = ITER_VAR(VAR)->prev,   \
++                                      ITER_VAR(PREV) != (LIST));              \
++         UPDATE_MULTIVAR_SAFE_LONG(VAR, PREV))
++
++#define LIST_FOR_EACH_SAFE(VAR, NEXT, MEMBER, LIST)                           \
++    for (INIT_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER, (LIST)->next,             \
++                                 struct ovs_list);                            \
++         CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER,                      \
++                                      ITER_VAR(VAR) != (LIST),                \
++                                      ITER_VAR(NEXT) = ITER_VAR(VAR)->next,   \
++                                      ITER_VAR(NEXT) != (LIST));              \
++         UPDATE_MULTIVAR_SAFE_LONG(VAR, NEXT))
++
++#define LIST_FOR_EACH_POP(ITER, MEMBER, LIST)                                 \
++    while (!ovs_list_is_empty(LIST) ?                                         \
++           (INIT_CONTAINER(ITER, ovs_list_pop_front(LIST), MEMBER), 1) :      \
++           (ITER = NULL, 0))
+ 
+ /* Inline implementations. */
+ 
 diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h
 index 1f81d830e7..4b9893388b 100644
 --- a/include/openvswitch/meta-flow.h
@@ -80936,6 +81163,161 @@ index 0000000000..a49563f071
 +#endif
 +
 +#endif /* usdt-probes.h */
+diff --git a/include/openvswitch/util.h b/include/openvswitch/util.h
+index 9189e6480b..9a924719bf 100644
+--- a/include/openvswitch/util.h
++++ b/include/openvswitch/util.h
+@@ -143,6 +143,150 @@ OVS_NO_RETURN void ovs_assert_failure(const char *, const char *, const char *);
+ #define INIT_CONTAINER(OBJECT, POINTER, MEMBER) \
+     ((OBJECT) = NULL, ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER))
+ 
++/* Multi-variable container iterators.
++ *
++ * The following macros facilitate safe iteration over data structures
++ * contained in objects. It does so by using an internal iterator variable of
++ * the type of the member object pointer (i.e: pointer to the data structure).
++ */
++
++/* Multi-variable iterator variable name.
++ * Returns the name of the internal iterator variable.
++ */
++#define ITER_VAR(NAME) NAME ## __iterator__
++
++/* Multi-variable initialization. Creates an internal iterator variable that
++ * points to the provided pointer. The type of the iterator variable is
++ * ITER_TYPE*. It must be the same type as &VAR->MEMBER.
++ *
++ * The _EXP version evaluates the extra expressions once.
++ */
++#define INIT_MULTIVAR(VAR, MEMBER, POINTER, ITER_TYPE)                  \
++    INIT_MULTIVAR_EXP(VAR, MEMBER, POINTER, ITER_TYPE, (void) 0)
++
++#define INIT_MULTIVAR_EXP(VAR, MEMBER, POINTER, ITER_TYPE, ...)         \
++    ITER_TYPE *ITER_VAR(VAR) = ( __VA_ARGS__ , (ITER_TYPE *) POINTER)
++
++/* Multi-variable condition.
++ * Evaluates the condition expression (that must be based on the internal
++ * iterator variable). Only if the result of expression is true, the OBJECT is
++ * set to the object containing the current value of the iterator variable.
++ *
++ * It is up to the caller to make sure it is safe to run OBJECT_CONTAINING on
++ * the pointers that verify the condition.
++ */
++#define CONDITION_MULTIVAR(VAR, MEMBER, EXPR)                                 \
++    ((EXPR) ?                                                                 \
++     (((VAR) = OBJECT_CONTAINING(ITER_VAR(VAR), VAR, MEMBER)), 1) :           \
++     (((VAR) = NULL), 0))
++
++/* Multi-variable update.
++ * Sets the iterator value to NEXT_ITER.
++ */
++#define UPDATE_MULTIVAR(VAR, NEXT_ITER)                                       \
++    (ITER_VAR(VAR) = NEXT_ITER)
++
++/* In the safe version of the multi-variable container iteration, the next
++ * value of the iterator is precalculated on the condition expression.
++ * This allows for the iterator to be freed inside the loop.
++ *
++ * Two versions of the macros are provided:
++ *
++ * * In the _SHORT version, the user does not have to provide a variable to
++ * store the next value of the iterator. Instead, a second iterator variable
++ * is declared in the INIT_ macro and its name is determined by
++ * ITER_NEXT_VAR(OBJECT).
++ *
++ * * In the _LONG version, the user provides another variable of the same type
++ * as the iterator object variable to store the next containing object.
++ * We still declare an iterator variable inside the loop but in this case it's
++ * name is derived from the name of the next containing variable.
++ * The value of the next containing object will only be set
++ * (via OBJECT_CONTAINING) if an additional condition is statisfied. This
++ * second condition must ensure it is safe to call OBJECT_CONTAINING on the
++ * next iterator variable.
++ * With respect to the value of the next containing object:
++ *  - Inside of the loop: the variable is either NULL or safe to use.
++ *  - Outside of the loop: the variable is NULL if the loop ends normally.
++ *     If the loop ends with a "break;" statement, rules of Inside the loop
++ *     apply.
++ */
++#define ITER_NEXT_VAR(NAME) NAME ## __iterator__next__
++
++/* Safe initialization declares both iterators. */
++#define INIT_MULTIVAR_SAFE_SHORT(VAR, MEMBER, POINTER, ITER_TYPE)             \
++    INIT_MULTIVAR_SAFE_SHORT_EXP(VAR, MEMBER, POINTER, ITER_TYPE, (void) 0)
++
++#define INIT_MULTIVAR_SAFE_SHORT_EXP(VAR, MEMBER, POINTER, ITER_TYPE, ...)    \
++    ITER_TYPE *ITER_VAR(VAR) = ( __VA_ARGS__ , (ITER_TYPE *) POINTER),        \
++        *ITER_NEXT_VAR(VAR) = NULL
++
++/* Evaluate the condition expression and, if satisfied, update the _next_
++ * iterator with the NEXT_EXPR.
++ * Both EXPR and NEXT_EXPR should only use ITER_VAR(VAR) and
++ * ITER_NEXT_VAR(VAR).
++ */
++#define CONDITION_MULTIVAR_SAFE_SHORT(VAR, MEMBER, EXPR, NEXT_EXPR)           \
++    ((EXPR) ?                                                                 \
++     (((VAR) = OBJECT_CONTAINING(ITER_VAR(VAR), VAR, MEMBER)),                \
++      (NEXT_EXPR), 1) :                                                       \
++     (((VAR) = NULL), 0))
++
++#define UPDATE_MULTIVAR_SAFE_SHORT(VAR)                                       \
++    UPDATE_MULTIVAR(VAR, ITER_NEXT_VAR(VAR))
++
++/* _LONG versions of the macros. */
++
++#define INIT_MULTIVAR_SAFE_LONG(VAR, NEXT_VAR, MEMBER, POINTER, ITER_TYPE)    \
++    INIT_MULTIVAR_SAFE_LONG_EXP(VAR, NEXT_VAR, MEMBER, POINTER, ITER_TYPE,    \
++                                (void) 0)                                     \
++
++#define INIT_MULTIVAR_SAFE_LONG_EXP(VAR, NEXT_VAR, MEMBER, POINTER,           \
++                                    ITER_TYPE, ...)                           \
++    ITER_TYPE  *ITER_VAR(VAR) = ( __VA_ARGS__ , (ITER_TYPE *) POINTER),       \
++        *ITER_VAR(NEXT_VAR) = NULL
++
++/* Evaluate the condition expression and, if satisfied, update the _next_
++ * iterator with the NEXT_EXPR. After, evaluate the NEXT_COND and, if
++ * satisfied, set the value to NEXT_VAR. NEXT_COND must use ITER_VAR(NEXT_VAR).
++ *
++ * Both EXPR and NEXT_EXPR should only use ITER_VAR(VAR) and
++ * ITER_VAR(NEXT_VAR).
++ */
++#define CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT_VAR, MEMBER, EXPR, NEXT_EXPR,  \
++                                     NEXT_COND)                               \
++    ((EXPR) ?                                                                 \
++     (((VAR) = OBJECT_CONTAINING(ITER_VAR(VAR), VAR, MEMBER)),                \
++      (NEXT_EXPR), ((NEXT_COND) ?                                             \
++       ((NEXT_VAR) =                                                          \
++        OBJECT_CONTAINING(ITER_VAR(NEXT_VAR), NEXT_VAR, MEMBER)) :            \
++       ((NEXT_VAR) = NULL)), 1) :                                             \
++     (((VAR) = NULL), ((NEXT_VAR) = NULL), 0))
++
++#define UPDATE_MULTIVAR_SAFE_LONG(VAR, NEXT_VAR)                              \
++    UPDATE_MULTIVAR(VAR, ITER_VAR(NEXT_VAR))
++
++/* Helpers to allow overloading the *_SAFE iterator macros and select either
++ * the LONG or the SHORT version depending on the number of arguments.
++ */
++#define GET_SAFE_MACRO2(_1, _2, NAME, ...) NAME
++#define GET_SAFE_MACRO3(_1, _2, _3, NAME, ...) NAME
++#define GET_SAFE_MACRO4(_1, _2, _3, _4, NAME, ...) NAME
++#define GET_SAFE_MACRO5(_1, _2, _3, _4, _5, NAME, ...) NAME
++#define GET_SAFE_MACRO6(_1, _2, _3, _4, _5, _6, NAME, ...) NAME
++#define GET_SAFE_MACRO(MAX_ARGS) GET_SAFE_MACRO ## MAX_ARGS
++
++/* MSVC treats __VA_ARGS__ as a simple token in argument lists. Introduce
++ * a level of indirection to work around that. */
++#define EXPAND_MACRO(name, args) name args
++
++/* Overload the LONG and the SHORT version of the macros. MAX_ARGS is the
++ * maximum number of arguments (i.e: the number of arguments of the LONG
++ * version). */
++#define OVERLOAD_SAFE_MACRO(LONG, SHORT, MAX_ARGS, ...) \
++        EXPAND_MACRO(GET_SAFE_MACRO(MAX_ARGS), \
++                     (__VA_ARGS__, LONG, SHORT))(__VA_ARGS__)
++
+ /* Returns the number of elements in ARRAY. */
+ #define ARRAY_SIZE(ARRAY) __ARRAY_SIZE(ARRAY)
+ 
 diff --git a/ipsec/ovs-monitor-ipsec.in b/ipsec/ovs-monitor-ipsec.in
 index 37e3703245..41ef886194 100755
 --- a/ipsec/ovs-monitor-ipsec.in
@@ -81621,6 +82003,53 @@ index d1bd4aa12a..f646a8f742 100644
  };
  
  enum {
+diff --git a/lib/cmap.h b/lib/cmap.h
+index d9db3c915c..8655f76d92 100644
+--- a/lib/cmap.h
++++ b/lib/cmap.h
+@@ -108,6 +108,8 @@ size_t cmap_replace(struct cmap *, struct cmap_node *old_node,
+  *
+  * CMAP and HASH are evaluated only once.  NODE is evaluated many times.
+  *
++ * After a normal exit of the loop (not through a "break;" statement) NODE is
++ * NULL.
+  *
+  * Thread-safety
+  * =============
+@@ -128,15 +130,15 @@ size_t cmap_replace(struct cmap *, struct cmap_node *old_node,
+  * CMAP_FOR_EACH_WITH_HASH_PROTECTED may only be used if CMAP is guaranteed not
+  * to change during iteration.  It may be very slightly faster.
+  */
+-#define CMAP_NODE_FOR_EACH(NODE, MEMBER, CMAP_NODE)                     \
+-    for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER);                       \
+-         (NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER);               \
+-         ASSIGN_CONTAINER(NODE, cmap_node_next(&(NODE)->MEMBER), MEMBER))
+-#define CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, CMAP_NODE)           \
+-    for (INIT_CONTAINER(NODE, CMAP_NODE, MEMBER);                       \
+-         (NODE) != OBJECT_CONTAINING(NULL, NODE, MEMBER);               \
+-         ASSIGN_CONTAINER(NODE, cmap_node_next_protected(&(NODE)->MEMBER), \
+-                          MEMBER))
++#define CMAP_NODE_FOR_EACH(NODE, MEMBER, CMAP_NODE)                        \
++    for (INIT_MULTIVAR(NODE, MEMBER, CMAP_NODE, struct cmap_node);         \
++         CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);         \
++         UPDATE_MULTIVAR(NODE, cmap_node_next(ITER_VAR(NODE))))
++#define CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, CMAP_NODE)              \
++    for (INIT_MULTIVAR(NODE, MEMBER, CMAP_NODE, struct cmap_node);         \
++         CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);         \
++         UPDATE_MULTIVAR(NODE, cmap_node_next_protected(ITER_VAR(NODE))))
++
+ #define CMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, CMAP)   \
+     CMAP_NODE_FOR_EACH(NODE, MEMBER, cmap_find(CMAP, HASH))
+ #define CMAP_FOR_EACH_WITH_HASH_PROTECTED(NODE, MEMBER, HASH, CMAP)     \
+@@ -223,7 +225,7 @@ unsigned long cmap_find_batch(const struct cmap *cmap, unsigned long map,
+      ? (INIT_CONTAINER(NODE, (CURSOR)->node, MEMBER),   \
+         cmap_cursor_advance(CURSOR),                    \
+         true)                                           \
+-     : false)
++     : (NODE = NULL, false))
+ 
+ #define CMAP_CURSOR_FOR_EACH(NODE, MEMBER, CURSOR, CMAP)    \
+     for (*(CURSOR) = cmap_cursor_start(CMAP);               \
 diff --git a/lib/conntrack-icmp.c b/lib/conntrack-icmp.c
 index 63246f0124..63ddd8038b 100644
 --- a/lib/conntrack-icmp.c
@@ -82980,6 +83409,75 @@ index 45bb96b543..f3f0358b36 100644
              }
          } else if (OVS_LIKELY(nw_proto == IPPROTO_UDP)) {
              if (OVS_LIKELY(size >= UDP_HEADER_LEN)) {
+diff --git a/lib/hindex.h b/lib/hindex.h
+index 876c5a9e39..f7a30d511a 100644
+--- a/lib/hindex.h
++++ b/lib/hindex.h
+@@ -128,18 +128,22 @@ void hindex_remove(struct hindex *, struct hindex_node *);
+  * Evaluates HASH only once.
+  */
+ #define HINDEX_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HINDEX)               \
+-    for (INIT_CONTAINER(NODE, hindex_node_with_hash(HINDEX, HASH), MEMBER); \
+-         NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER);                     \
+-         ASSIGN_CONTAINER(NODE, (NODE)->MEMBER.s, MEMBER))
++    for (INIT_MULTIVAR(NODE, MEMBER, hindex_node_with_hash(HINDEX, HASH),   \
++                       struct hindex_node);                                 \
++         CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);          \
++         UPDATE_MULTIVAR(NODE, ITER_VAR(NODE)->s))
+ 
+ /* Safe when NODE may be freed (not needed when NODE may be removed from the
+  * hash map but its members remain accessible and intact). */
+-#define HINDEX_FOR_EACH_WITH_HASH_SAFE(NODE, NEXT, MEMBER, HASH, HINDEX) \
+-    for (INIT_CONTAINER(NODE, hindex_node_with_hash(HINDEX, HASH), MEMBER); \
+-         (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)                 \
+-          ? INIT_CONTAINER(NEXT, (NODE)->MEMBER.s, MEMBER), 1           \
+-          : 0);                                                         \
+-         (NODE) = (NEXT))
++#define HINDEX_FOR_EACH_WITH_HASH_SAFE(NODE, NEXT, MEMBER, HASH, HINDEX)    \
++    for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,                        \
++                                hindex_node_with_hash(HINDEX, HASH),        \
++                                struct hindex_node);                        \
++         CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,                   \
++                                      ITER_VAR(NODE) != NULL,               \
++                                      ITER_VAR(NEXT) = ITER_VAR(NODE)->s,   \
++                                      ITER_VAR(NEXT) != NULL);              \
++         UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
+ 
+ /* Returns the head node in 'hindex' with the given 'hash', or a null pointer
+  * if no nodes have that hash value. */
+@@ -157,19 +161,22 @@ hindex_node_with_hash(const struct hindex *hindex, size_t hash)
+ /* Iteration. */
+ 
+ /* Iterates through every node in HINDEX. */
+-#define HINDEX_FOR_EACH(NODE, MEMBER, HINDEX)                           \
+-    for (INIT_CONTAINER(NODE, hindex_first(HINDEX), MEMBER);            \
+-         NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER);                 \
+-         ASSIGN_CONTAINER(NODE, hindex_next(HINDEX, &(NODE)->MEMBER), MEMBER))
++#define HINDEX_FOR_EACH(NODE, MEMBER, HINDEX)                                 \
++    for (INIT_MULTIVAR(NODE, MEMBER, hindex_first(HINDEX),                    \
++                       struct hindex_node);                                   \
++         CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL);            \
++         UPDATE_MULTIVAR(NODE, hindex_next(HINDEX, ITER_VAR(NODE))))
+ 
+ /* Safe when NODE may be freed (not needed when NODE may be removed from the
+  * hash index but its members remain accessible and intact). */
+-#define HINDEX_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HINDEX)              \
+-    for (INIT_CONTAINER(NODE, hindex_first(HINDEX), MEMBER);          \
+-         (NODE != OBJECT_CONTAINING(NULL, NODE, MEMBER)                 \
+-          ? INIT_CONTAINER(NEXT, hindex_next(HINDEX, &(NODE)->MEMBER), MEMBER), 1 \
+-          : 0);                                                         \
+-         (NODE) = (NEXT))
++#define HINDEX_FOR_EACH_SAFE(NODE, NEXT, MEMBER, HINDEX)                      \
++    for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, hindex_first(HINDEX),    \
++                                 struct hindex_node);                         \
++         CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER,                     \
++                                      ITER_VAR(NODE) != NULL,                 \
++                        ITER_VAR(NEXT) = hindex_next(HINDEX, ITER_VAR(NODE)), \
++                                      ITER_VAR(NEXT) != NULL);                \
++         UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT))
+ 
+ struct hindex_node *hindex_first(const struct hindex *);
+ struct hindex_node *hindex_next(const struct hindex *,
 diff --git a/lib/ipf.c b/lib/ipf.c
 index 446e89d13c..009f5d1e9b 100644
 --- a/lib/ipf.c
@@ -85419,6 +85917,22 @@ index ab8e08b84d..8f8c9041ac 100644
            <p>
              Open vSwitch 2.6 introduced <code>nat</code>.  Linux 4.6 was the
              earliest upstream kernel that implemented <code>ct</code> support for
+diff --git a/lib/ovs-numa.h b/lib/ovs-numa.h
+index 8f2ea34308..8d141b41e3 100644
+--- a/lib/ovs-numa.h
++++ b/lib/ovs-numa.h
+@@ -66,9 +66,9 @@ void ovs_numa_dump_destroy(struct ovs_numa_dump *);
+ int ovs_numa_thread_setaffinity_core(unsigned core_id);
+ 
+ #define FOR_EACH_CORE_ON_DUMP(ITER, DUMP)                    \
+-    HMAP_FOR_EACH((ITER), hmap_node, &(DUMP)->cores)
++    HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->cores)
+ 
+ #define FOR_EACH_NUMA_ON_DUMP(ITER, DUMP)                    \
+-    HMAP_FOR_EACH((ITER), hmap_node, &(DUMP)->numas)
++    HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->numas)
+ 
+ #endif /* ovs-numa.h */
 diff --git a/lib/ovs-rcu.c b/lib/ovs-rcu.c
 index ebc8120f0f..cde1e925ba 100644
 --- a/lib/ovs-rcu.c
@@ -86373,6 +86887,98 @@ index b990ed9d59..0d3290dc37 100644
      cursor.vector = impl->vector;
      cursor.entry_idx = -1;
  
+diff --git a/lib/rculist.h b/lib/rculist.h
+index 1072b87af2..c0d77acf94 100644
+--- a/lib/rculist.h
++++ b/lib/rculist.h
+@@ -365,35 +365,57 @@ rculist_is_singleton_protected(const struct rculist *list)
+     return list_next == list->prev && list_next != list;
+ }
+ 
+-#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST)                         \
+-    for (INIT_CONTAINER(ITER, rculist_next(RCULIST), MEMBER);           \
+-         &(ITER)->MEMBER != (RCULIST);                                  \
+-         ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER))
+-#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST)                \
+-    for (ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER); \
+-         &(ITER)->MEMBER != (RCULIST);                                  \
+-         ASSIGN_CONTAINER(ITER, rculist_next(&(ITER)->MEMBER), MEMBER))
+-
+-#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST)       \
+-    for (INIT_CONTAINER(ITER, (RCULIST)->prev, MEMBER);                 \
+-         &(ITER)->MEMBER != (RCULIST);                                  \
+-         ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
+-#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST) \
+-    for (ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER);           \
+-         &(ITER)->MEMBER != (RCULIST);                                  \
+-         ASSIGN_CONTAINER(ITER, (ITER)->MEMBER.prev, MEMBER))
+-
+-#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST)               \
+-    for (INIT_CONTAINER(ITER, rculist_next_protected(RCULIST), MEMBER); \
+-         &(ITER)->MEMBER != (RCULIST);                                  \
+-         ASSIGN_CONTAINER(ITER, rculist_next_protected(&(ITER)->MEMBER), \
+-                          MEMBER))
+-
+-#define RCULIST_FOR_EACH_SAFE_PROTECTED(ITER, NEXT, MEMBER, RCULIST)    \
+-    for (INIT_CONTAINER(ITER, rculist_next_protected(RCULIST), MEMBER); \
+-         (&(ITER)->MEMBER != (RCULIST)                                  \
+-          ? INIT_CONTAINER(NEXT, rculist_next_protected(&(ITER)->MEMBER), \
+-                           MEMBER), 1 : 0);                             \
+-         (ITER) = (NEXT))
++#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST)                               \
++    for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(RCULIST),                   \
++                       const struct rculist);                                 \
++         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
++         UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER))))
++
++#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST)                      \
++    for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(&(ITER)->MEMBER),           \
++                       const struct rculist);                                 \
++         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
++         UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER))))
++
++#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST)             \
++    for (INIT_MULTIVAR(ITER, MEMBER, (RCULIST)->prev, struct rculist);        \
++         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
++         UPDATE_MULTIVAR(ITER, ITER_VAR(VAR).prev))
++
++#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST)    \
++    for (INIT_MULTIVAR(ITER, MEMBER, (ITER)->MEMBER.prev, struct rculist);    \
++         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
++         UPDATE_MULTIVAR(ITER, ITER_VAR(VAR).prev))
++
++#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST)                     \
++    for (INIT_MULTIVAR(ITER, MEMBER, rculist_next_protected(RCULIST),         \
++                       struct rculist);                                       \
++         CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST));       \
++         UPDATE_MULTIVAR(ITER, rculist_next_protected(ITER_VAR(ITER)))        \
++
++#define RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED(ITER, MEMBER, RCULIST)          \
++    for (INIT_MULTIVAR_SAFE_SHORT(ITER, MEMBER,                               \
++                                  rculist_next_protected(RCULIST),            \
++                                  struct rculist);                            \
++         CONDITION_MULTIVAR_SAFE_SHORT(ITER, MEMBER,                          \
++                                       ITER_VAR(ITER) != (RCULIST),           \
++             ITER_NEXT_VAR(ITER) = rculist_next_protected(ITER_VAR(VAR)));    \
++        UPDATE_MULTIVAR_SHORT(ITER))
++
++#define RCULIST_FOR_EACH_SAFE_LONG_PROTECTED(ITER, NEXT, MEMBER, RCULIST)     \
++    for (INIT_MULTIVAR_SAFE_LONG(ITER, NEXT, MEMBER,                          \
++                                 rculist_next_protected(RCULIST)              \
++                                 struct rculist);                             \
++         CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER                       \
++                                      ITER_VAR(ITER) != (RCULIST),            \
++             ITER_VAR(NEXT) = rculist_next_protected(ITER_VAR(VAR)),          \
++                                      ITER_VAR(NEXT) != (RCULIST));           \
++        UPDATE_MULTIVAR_LONG(ITER))
++
++#define RCULIST_FOR_EACH_SAFE_PROTECTED(...)                                  \
++    OVERLOAD_SAFE_MACRO(RCULIST_FOR_EACH_SAFE_LONG_PROTECTED,                 \
++                        RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED,                \
++                        4, __VA_ARGS__)
++
+ 
+ #endif /* rculist.h */
 diff --git a/lib/reconnect.c b/lib/reconnect.c
 index c89abab889..a929ddfd2d 100644
 --- a/lib/reconnect.c
@@ -87587,6 +88193,19 @@ index add3aabcc2..391d6d8f7c 100644
  dnl Checks for MSVC x64 compiler.
  AC_DEFUN([OVS_CHECK_WIN64],
    [AC_CACHE_CHECK(
+diff --git a/ofproto/bond.c b/ofproto/bond.c
+index 405202fb64..54e06211a6 100644
+--- a/ofproto/bond.c
++++ b/ofproto/bond.c
+@@ -1165,7 +1165,7 @@ insert_bal(struct ovs_list *bals, struct bond_slave *slave)
+             break;
+         }
+     }
+-    ovs_list_insert(&pos->bal_node, &slave->bal_node);
++    ovs_list_insert(pos ? &pos->bal_node : bals, &slave->bal_node);
+ }
+ 
+ /* Removes 'slave' from its current list and then inserts it into 'bals' so
 diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
 index 51d656cba9..fd926cbb82 100644
 --- a/ofproto/connmgr.c
@@ -94068,6 +94687,34 @@ index 6d53d016de..2d98fad485 100644
      }
      assert(n_rules <= cls->n_rules);
  }
+diff --git a/tests/test-cmap.c b/tests/test-cmap.c
+index 0705475606..f8cc4dd80a 100644
+--- a/tests/test-cmap.c
++++ b/tests/test-cmap.c
+@@ -74,6 +74,7 @@ check_cmap(struct cmap *cmap, const int values[], size_t n,
+         cmap_values[i++] = e->value;
+     }
+     assert(i == n);
++    assert(e == NULL);
+ 
+     /* Here we test iteration with cmap_next_position() */
+     i = 0;
+@@ -107,6 +108,7 @@ check_cmap(struct cmap *cmap, const int values[], size_t n,
+             count += e->value == values[i];
+         }
+         assert(count == 1);
++        assert(e == NULL);
+     }
+ 
+     /* Check that all the values are there in batched lookup. */
+@@ -130,6 +132,7 @@ check_cmap(struct cmap *cmap, const int values[], size_t n,
+             CMAP_NODE_FOR_EACH (e, node, nodes[k]) {
+                 count += e->value == values[i + k];
+             }
++            assert(e == NULL);
+         }
+         assert(count == j); /* j elements in a batch. */
+     }
 diff --git a/tests/test-conntrack.c b/tests/test-conntrack.c
 index f77ee75e38..da1ac63b6c 100644
 --- a/tests/test-conntrack.c
@@ -94090,6 +94737,79 @@ index f77ee75e38..da1ac63b6c 100644
      }
      ovs_barrier_block(&barrier);
      destroy_packets(pkt_batch);
+diff --git a/tests/test-hindex.c b/tests/test-hindex.c
+index af06be5fcc..95e49284ee 100644
+--- a/tests/test-hindex.c
++++ b/tests/test-hindex.c
+@@ -265,6 +265,11 @@ test_hindex_for_each_safe(hash_func *hash)
+             i = 0;
+             n_remaining = n;
+             HINDEX_FOR_EACH_SAFE (e, next, node, &hindex) {
++                if (hindex_next(&hindex, &e->node) == NULL) {
++                    assert(next == NULL);
++                } else {
++                    assert(&next->node == hindex_next(&hindex, &e->node));
++                }
+                 assert(i < n);
+                 if (pattern & (1ul << e->value)) {
+                     size_t j;
+@@ -281,6 +286,7 @@ test_hindex_for_each_safe(hash_func *hash)
+                 i++;
+             }
+             assert(i == n);
++            assert(next == NULL);
+ 
+             for (i = 0; i < n; i++) {
+                 if (pattern & (1ul << i)) {
+diff --git a/tests/test-hmap.c b/tests/test-hmap.c
+index 9259b0b3fc..47b4755386 100644
+--- a/tests/test-hmap.c
++++ b/tests/test-hmap.c
+@@ -62,6 +62,7 @@ check_hmap(struct hmap *hmap, const int values[], size_t n,
+         hmap_values[i++] = e->value;
+     }
+     assert(i == n);
++    assert(e == NULL);
+ 
+     memcpy(sort_values, values, sizeof *sort_values * n);
+     qsort(sort_values, n, sizeof *sort_values, compare_ints);
+@@ -82,6 +83,7 @@ check_hmap(struct hmap *hmap, const int values[], size_t n,
+             count += e->value == values[i];
+         }
+         assert(count == 1);
++        assert(e == NULL);
+     }
+ 
+     /* Check counters. */
+@@ -243,6 +245,11 @@ test_hmap_for_each_safe(hash_func *hash)
+             i = 0;
+             n_remaining = n;
+             HMAP_FOR_EACH_SAFE (e, next, node, &hmap) {
++                if (hmap_next(&hmap, &e->node) == NULL) {
++                    assert(next == NULL);
++                } else {
++                    assert(&next->node == hmap_next(&hmap, &e->node));
++                }
+                 assert(i < n);
+                 if (pattern & (1ul << e->value)) {
+                     size_t j;
+@@ -259,6 +266,8 @@ test_hmap_for_each_safe(hash_func *hash)
+                 i++;
+             }
+             assert(i == n);
++            assert(next == NULL);
++            assert(e == NULL);
+ 
+             for (i = 0; i < n; i++) {
+                 if (pattern & (1ul << i)) {
+@@ -308,6 +317,7 @@ test_hmap_for_each_pop(hash_func *hash)
+             i++;
+         }
+         assert(i == n);
++        assert(e == NULL);
+ 
+         hmap_destroy(&hmap);
+     }
 diff --git a/tests/test-jsonrpc.py b/tests/test-jsonrpc.py
 index 3eabcd78d5..1df5afa221 100644
 --- a/tests/test-jsonrpc.py
@@ -94115,6 +94835,52 @@ index d7854a1df3..32a77392c6 100755
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
+diff --git a/tests/test-list.c b/tests/test-list.c
+index 6f1fb059bc..648e02a5e2 100644
+--- a/tests/test-list.c
++++ b/tests/test-list.c
+@@ -61,7 +61,7 @@ check_list(struct ovs_list *list, const int values[], size_t n)
+         assert(e->value == values[i]);
+         i++;
+     }
+-    assert(&e->node == list);
++    assert(e == NULL);
+     assert(i == n);
+ 
+     i = 0;
+@@ -70,7 +70,7 @@ check_list(struct ovs_list *list, const int values[], size_t n)
+         assert(e->value == values[n - i - 1]);
+         i++;
+     }
+-    assert(&e->node == list);
++    assert(e == NULL);
+     assert(i == n);
+ 
+     assert(ovs_list_is_empty(list) == !n);
+@@ -135,6 +135,13 @@ test_list_for_each_safe(void)
+             values_idx = 0;
+             n_remaining = n;
+             LIST_FOR_EACH_SAFE (e, next, node, &list) {
++                /* "next" is valid as long as it's not pointing to &list. */
++                if (&e->node == list.prev) {
++                    assert(next == NULL);
++                } else {
++                    assert(&next->node == e->node.next);
++                }
++
+                 assert(i < n);
+                 if (pattern & (1ul << i)) {
+                     ovs_list_remove(&e->node);
+@@ -148,7 +155,8 @@ test_list_for_each_safe(void)
+                 i++;
+             }
+             assert(i == n);
+-            assert(&e->node == &list);
++            assert(e == NULL);
++            assert(next == NULL);
+ 
+             for (i = 0; i < n; i++) {
+                 if (pattern & (1ul << i)) {
 diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
 index b1a4be36bb..c4845956ca 100644
 --- a/tests/test-ovsdb.c
diff --git a/SPECS/openvswitch2.13.spec b/SPECS/openvswitch2.13.spec
index 121e9b8..1e52cae 100644
--- a/SPECS/openvswitch2.13.spec
+++ b/SPECS/openvswitch2.13.spec
@@ -59,7 +59,7 @@ Summary: Open vSwitch
 Group: System Environment/Daemons daemon/database/utilities
 URL: http://www.openvswitch.org/
 Version: 2.13.0
-Release: 170%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist}
+Release: 171%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist}
 
 # Nearly all of openvswitch is ASL 2.0.  The bugtool is LGPLv2+, and the
 # lib/sflow*.[ch] files are SISSL
@@ -715,6 +715,22 @@ exit 0
 %endif
 
 %changelog
+* Wed Mar 30 2022 Open vSwitch CI <ovs-ci@redhat.com> - 2.13.0-171
+- Merging upstream branch-2.13 [RH git: 7763266297]
+    Commit list:
+    3894437f6c sparse: bump recommended version and include headers.
+    c7f0d6113a rculist: use multi-variable helpers for loop macros.
+    019895b832 hindex: use multi-variable iterators.
+    9f176f7025 cmap: use multi-variable iterators.
+    e3e1e2045c hmap: implement UB-safe hmap pop iterator.
+    6aa8de0291 hmap: use multi-variable helpers for hmap loops.
+    72a9f2d75f hmap: Fix Coverity false positive
+    f7083afb85 list: use multi-variable helpers for list loops.
+    57c44fa35e util: add helpers to overload SAFE macro.
+    69acaa187b util: add safe multi-variable iterators.
+    2c56295e27 util: add multi-variable loop iterator macros.
+
+
 * Wed Mar 30 2022 Open vSwitch CI <ovs-ci@redhat.com> - 2.13.0-170
 - Merging upstream branch-2.13 [RH git: 7ec8e5d0e5]
     Commit list: