diff --git a/SOURCES/openvswitch-2.16.0.patch b/SOURCES/openvswitch-2.16.0.patch
index a9758fe..aa9ed13 100644
--- a/SOURCES/openvswitch-2.16.0.patch
+++ b/SOURCES/openvswitch-2.16.0.patch
@@ -93,16 +93,20 @@ index d8fa931fab..1dbead3276 100644
  .. note::
  
 diff --git a/NEWS b/NEWS
-index 559a51ba3f..139c24a4f8 100644
+index 559a51ba3f..ecaf9ffd78 100644
 --- a/NEWS
 +++ b/NEWS
-@@ -1,3 +1,13 @@
-+v2.16.2 - xx xxx xxxx
+@@ -1,3 +1,17 @@
++v2.16.3 - xx xxx xxxx
 +---------------------
 +   - Python:
 +     * For SSL support, the use of the pyOpenSSL library has been replaced
 +       with the native 'ssl' module.
 +
++v2.16.2 - 17 Dec 2021
++---------------------
++   - Bug fixes
++
 +v2.16.1 - 21 Oct 2021
 +---------------------
 +   - Bug fixes
@@ -111,7 +115,7 @@ index 559a51ba3f..139c24a4f8 100644
  ---------------------
     - Removed support for 1024-bit Diffie-Hellman key exchange, which is now
 diff --git a/configure.ac b/configure.ac
-index 16b32be965..64c26828f2 100644
+index 16b32be965..92817b62e1 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -13,7 +13,7 @@
@@ -119,7 +123,7 @@ index 16b32be965..64c26828f2 100644
  
  AC_PREREQ(2.63)
 -AC_INIT(openvswitch, 2.16.0, bugs@openvswitch.org)
-+AC_INIT(openvswitch, 2.16.2, bugs@openvswitch.org)
++AC_INIT(openvswitch, 2.16.3, bugs@openvswitch.org)
  AC_CONFIG_SRCDIR([datapath/datapath.c])
  AC_CONFIG_MACRO_DIR([m4])
  AC_CONFIG_AUX_DIR([build-aux])
@@ -392,16 +396,42 @@ index 2b314ce274..74130a4600 100644
                        const PNL_ATTR actions);
  
  /*
+diff --git a/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h b/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
+index 4cce92f66c..bc18c56b81 100644
+--- a/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
++++ b/datapath/linux/compat/include/net/netfilter/nf_conntrack_core.h
+@@ -108,7 +108,14 @@ static inline bool rpl_nf_ct_delete(struct nf_conn *ct, u32 portid, int report)
+ static inline unsigned int
+ rpl_nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state)
+ {
+-	return nf_conntrack_in(state->net, state->pf, state->hook, skb);
++	int err;
++
++	/* Repeat if requested, see nf_iterate(). */
++	do {
++		err = nf_conntrack_in(state->net, state->pf, state->hook, skb);
++	} while (err == NF_REPEAT);
++
++	return err;
+ }
+ #define nf_conntrack_in rpl_nf_conntrack_in
+ #endif /* HAVE_NF_CONNTRACK_IN_TAKES_NF_HOOK_STATE */
 diff --git a/debian/changelog b/debian/changelog
-index 239d210b96..a0838ea3d7 100644
+index 239d210b96..9fa140c6ff 100644
 --- a/debian/changelog
 +++ b/debian/changelog
-@@ -1,3 +1,15 @@
+@@ -1,3 +1,21 @@
++openvswitch (2.16.3-1) unstable; urgency=low
++   [ Open vSwitch team ]
++   * New upstream version
++
++ -- Open vSwitch team <dev@openvswitch.org>  Fri, 17 Dec 2021 22:14:03 +0100
++
 +openvswitch (2.16.2-1) unstable; urgency=low
 +   [ Open vSwitch team ]
 +   * New upstream version
 +
-+ -- Open vSwitch team <dev@openvswitch.org>  Thu, 21 Oct 2021 23:58:12 +0200
++ -- Open vSwitch team <dev@openvswitch.org>  Fri, 17 Dec 2021 22:14:03 +0100
 +
 +openvswitch (2.16.1-1) unstable; urgency=low
 +   [ Open vSwitch team ]
@@ -614,6 +644,161 @@ index b7d577870d..fe24f9abdf 100644
                    "cannot use CPU flag based optimizations");
      return false;
  }
+diff --git a/lib/dpif-netdev-extract-avx512.c b/lib/dpif-netdev-extract-avx512.c
+index ec64419e38..8d8003b05f 100644
+--- a/lib/dpif-netdev-extract-avx512.c
++++ b/lib/dpif-netdev-extract-avx512.c
+@@ -161,6 +161,15 @@ _mm512_maskz_permutexvar_epi8_wrap(__mmask64 kmask, __m512i idx, __m512i a)
+ #define PATTERN_IPV4_UDP PATTERN_IPV4_GEN(0x45, 0, 0, 0x11)
+ #define PATTERN_IPV4_TCP PATTERN_IPV4_GEN(0x45, 0, 0, 0x06)
+ 
++#define PATTERN_TCP_GEN(data_offset)                                    \
++  0, 0, 0, 0, /* sport, dport */                                        \
++  0, 0, 0, 0, /* sequence number */                                     \
++  0, 0, 0, 0, /* ack number */                                          \
++  data_offset, /* data offset: used to verify = 5, options not supported */
++
++#define PATTERN_TCP_MASK PATTERN_TCP_GEN(0xF0)
++#define PATTERN_TCP PATTERN_TCP_GEN(0x50)
++
+ #define NU 0
+ #define PATTERN_IPV4_UDP_SHUFFLE \
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, NU, NU, /* Ether */ \
+@@ -320,8 +329,16 @@ static const struct mfex_profile mfex_profiles[PROFILE_COUNT] =
+     },
+ 
+     [PROFILE_ETH_IPV4_TCP] = {
+-        .probe_mask.u8_data = { PATTERN_ETHERTYPE_MASK PATTERN_IPV4_MASK },
+-        .probe_data.u8_data = { PATTERN_ETHERTYPE_IPV4 PATTERN_IPV4_TCP},
++        .probe_mask.u8_data = {
++            PATTERN_ETHERTYPE_MASK
++            PATTERN_IPV4_MASK
++            PATTERN_TCP_MASK
++        },
++        .probe_data.u8_data = {
++            PATTERN_ETHERTYPE_IPV4
++            PATTERN_IPV4_TCP
++            PATTERN_TCP
++        },
+ 
+         .store_shuf.u8_data = { PATTERN_IPV4_TCP_SHUFFLE },
+         .store_kmsk = PATTERN_IPV4_TCP_KMASK,
+@@ -353,10 +370,16 @@ static const struct mfex_profile mfex_profiles[PROFILE_COUNT] =
+ 
+     [PROFILE_ETH_VLAN_IPV4_TCP] = {
+         .probe_mask.u8_data = {
+-            PATTERN_ETHERTYPE_MASK PATTERN_DT1Q_MASK PATTERN_IPV4_MASK
++            PATTERN_ETHERTYPE_MASK
++            PATTERN_DT1Q_MASK
++            PATTERN_IPV4_MASK
++            PATTERN_TCP_MASK
+         },
+         .probe_data.u8_data = {
+-            PATTERN_ETHERTYPE_DT1Q PATTERN_DT1Q_IPV4 PATTERN_IPV4_TCP
++            PATTERN_ETHERTYPE_DT1Q
++            PATTERN_DT1Q_IPV4
++            PATTERN_IPV4_TCP
++            PATTERN_TCP
+         },
+ 
+         .store_shuf.u8_data = { PATTERN_DT1Q_IPV4_TCP_SHUFFLE },
+@@ -374,16 +397,31 @@ static const struct mfex_profile mfex_profiles[PROFILE_COUNT] =
+ /* Protocol specific helper functions, for calculating offsets/lenghts. */
+ static int32_t
+ mfex_ipv4_set_l2_pad_size(struct dp_packet *pkt, struct ip_header *nh,
+-                          uint32_t len_from_ipv4)
++                          uint32_t len_from_ipv4, uint32_t next_proto_len)
+ {
+-        /* Handle dynamic l2_pad_size. */
+-        uint16_t tot_len = ntohs(nh->ip_tot_len);
+-        if (OVS_UNLIKELY(tot_len > len_from_ipv4 ||
+-                (len_from_ipv4 - tot_len) > UINT16_MAX)) {
+-            return -1;
+-        }
+-        dp_packet_set_l2_pad_size(pkt, len_from_ipv4 - tot_len);
+-        return 0;
++    /* Handle dynamic l2_pad_size; note that avx512 has already validated
++     * the IP->ihl field to be 5, so 20 bytes of IP header (no options).
++     */
++    uint16_t ip_tot_len = ntohs(nh->ip_tot_len);
++
++    /* Error if IP total length is greater than remaining packet size. */
++    bool err_ip_tot_len_too_high = ip_tot_len > len_from_ipv4;
++
++    /* Error if IP total length is less than the size of the IP header
++     * itself, and the size of the next-protocol this profile matches on.
++     */
++    bool err_ip_tot_len_too_low =
++        (IP_HEADER_LEN + next_proto_len) > ip_tot_len;
++
++    /* Ensure the l2 pad size will not overflow. */
++    bool err_len_u16_overflow = (len_from_ipv4 - ip_tot_len) > UINT16_MAX;
++
++    if (OVS_UNLIKELY(err_ip_tot_len_too_high || err_ip_tot_len_too_low ||
++                     err_len_u16_overflow)) {
++        return -1;
++    }
++    dp_packet_set_l2_pad_size(pkt, len_from_ipv4 - ip_tot_len);
++    return 0;
+ }
+ 
+ /* Fixup the VLAN CFI and PCP, reading the PCP from the input to this function,
+@@ -450,7 +488,14 @@ mfex_avx512_process(struct dp_packet_batch *packets,
+ 
+         /* Load packet data and probe with AVX512 mask & compare. */
+         const uint8_t *pkt = dp_packet_data(packet);
+-        __m512i v_pkt0 = _mm512_loadu_si512(pkt);
++        __m512i v_pkt0;
++        if (size >= 64) {
++            v_pkt0 = _mm512_loadu_si512(pkt);
++        } else {
++            uint64_t load_kmask = (1ULL << size) - 1;
++            v_pkt0 = _mm512_maskz_loadu_epi8(load_kmask, pkt);
++        }
++
+         __m512i v_pkt0_masked = _mm512_and_si512(v_pkt0, v_mask);
+         __mmask64 k_cmp = _mm512_cmpeq_epi8_mask(v_pkt0_masked, v_vals);
+         if (k_cmp != UINT64_MAX) {
+@@ -498,7 +543,8 @@ mfex_avx512_process(struct dp_packet_batch *packets,
+ 
+                 uint32_t size_from_ipv4 = size - VLAN_ETH_HEADER_LEN;
+                 struct ip_header *nh = (void *)&pkt[VLAN_ETH_HEADER_LEN];
+-                if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4)) {
++                if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4,
++                                              TCP_HEADER_LEN)) {
+                     continue;
+                 }
+ 
+@@ -512,7 +558,8 @@ mfex_avx512_process(struct dp_packet_batch *packets,
+ 
+                 uint32_t size_from_ipv4 = size - VLAN_ETH_HEADER_LEN;
+                 struct ip_header *nh = (void *)&pkt[VLAN_ETH_HEADER_LEN];
+-                if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4)) {
++                if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4,
++                                              UDP_HEADER_LEN)) {
+                     continue;
+                 }
+             } break;
+@@ -525,7 +572,8 @@ mfex_avx512_process(struct dp_packet_batch *packets,
+                 /* Handle dynamic l2_pad_size. */
+                 uint32_t size_from_ipv4 = size - sizeof(struct eth_header);
+                 struct ip_header *nh = (void *)&pkt[sizeof(struct eth_header)];
+-                if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4)) {
++                if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4,
++                                              TCP_HEADER_LEN)) {
+                     continue;
+                 }
+             } break;
+@@ -534,7 +582,8 @@ mfex_avx512_process(struct dp_packet_batch *packets,
+                 /* Handle dynamic l2_pad_size. */
+                 uint32_t size_from_ipv4 = size - sizeof(struct eth_header);
+                 struct ip_header *nh = (void *)&pkt[sizeof(struct eth_header)];
+-                if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4)) {
++                if (mfex_ipv4_set_l2_pad_size(packet, nh, size_from_ipv4,
++                                              UDP_HEADER_LEN)) {
+                     continue;
+                 }
+ 
 diff --git a/lib/dpif-netdev-private-dfc.h b/lib/dpif-netdev-private-dfc.h
 index 92092ebec9..3dfc91f0fe 100644
 --- a/lib/dpif-netdev-private-dfc.h
@@ -1906,11 +2091,231 @@ index b30a11c24b..41835f6f4d 100644
          return NULL;
      }
  
+diff --git a/lib/tnl-neigh-cache.c b/lib/tnl-neigh-cache.c
+index 5bda4af7e0..995c88bf17 100644
+--- a/lib/tnl-neigh-cache.c
++++ b/lib/tnl-neigh-cache.c
+@@ -32,6 +32,7 @@
+ #include "errno.h"
+ #include "flow.h"
+ #include "netdev.h"
++#include "ovs-atomic.h"
+ #include "ovs-thread.h"
+ #include "packets.h"
+ #include "openvswitch/poll-loop.h"
+@@ -44,14 +45,13 @@
+ #include "openvswitch/vlog.h"
+ 
+ 
+-/* In seconds */
+-#define NEIGH_ENTRY_DEFAULT_IDLE_TIME  (15 * 60)
++#define NEIGH_ENTRY_DEFAULT_IDLE_TIME_MS  (15 * 60 * 1000)
+ 
+ struct tnl_neigh_entry {
+     struct cmap_node cmap_node;
+     struct in6_addr ip;
+     struct eth_addr mac;
+-    time_t expires;             /* Expiration time. */
++    atomic_llong expires;       /* Expiration time in ms. */
+     char br_name[IFNAMSIZ];
+ };
+ 
+@@ -64,6 +64,16 @@ tnl_neigh_hash(const struct in6_addr *ip)
+     return hash_bytes(ip->s6_addr, 16, 0);
+ }
+ 
++static bool
++tnl_neigh_expired(struct tnl_neigh_entry *neigh)
++{
++    long long expires;
++
++    atomic_read_explicit(&neigh->expires, &expires, memory_order_acquire);
++
++    return expires <= time_msec();
++}
++
+ static struct tnl_neigh_entry *
+ tnl_neigh_lookup__(const char br_name[IFNAMSIZ], const struct in6_addr *dst)
+ {
+@@ -73,11 +83,13 @@ tnl_neigh_lookup__(const char br_name[IFNAMSIZ], const struct in6_addr *dst)
+     hash = tnl_neigh_hash(dst);
+     CMAP_FOR_EACH_WITH_HASH (neigh, cmap_node, hash, &table) {
+         if (ipv6_addr_equals(&neigh->ip, dst) && !strcmp(neigh->br_name, br_name)) {
+-            if (neigh->expires <= time_now()) {
++            if (tnl_neigh_expired(neigh)) {
+                 return NULL;
+             }
+ 
+-            neigh->expires = time_now() + NEIGH_ENTRY_DEFAULT_IDLE_TIME;
++            atomic_store_explicit(&neigh->expires, time_msec() +
++                                  NEIGH_ENTRY_DEFAULT_IDLE_TIME_MS,
++                                  memory_order_release);
+             return neigh;
+         }
+     }
+@@ -113,15 +125,16 @@ tnl_neigh_delete(struct tnl_neigh_entry *neigh)
+     ovsrcu_postpone(neigh_entry_free, neigh);
+ }
+ 
+-static void
+-tnl_neigh_set__(const char name[IFNAMSIZ], const struct in6_addr *dst,
+-                const struct eth_addr mac)
++void
++tnl_neigh_set(const char name[IFNAMSIZ], const struct in6_addr *dst,
++              const struct eth_addr mac)
+ {
+     ovs_mutex_lock(&mutex);
+     struct tnl_neigh_entry *neigh = tnl_neigh_lookup__(name, dst);
+     if (neigh) {
+         if (eth_addr_equals(neigh->mac, mac)) {
+-            neigh->expires = time_now() + NEIGH_ENTRY_DEFAULT_IDLE_TIME;
++            atomic_store_relaxed(&neigh->expires, time_msec() +
++                                 NEIGH_ENTRY_DEFAULT_IDLE_TIME_MS);
+             ovs_mutex_unlock(&mutex);
+             return;
+         }
+@@ -133,7 +146,8 @@ tnl_neigh_set__(const char name[IFNAMSIZ], const struct in6_addr *dst,
+ 
+     neigh->ip = *dst;
+     neigh->mac = mac;
+-    neigh->expires = time_now() + NEIGH_ENTRY_DEFAULT_IDLE_TIME;
++    atomic_store_relaxed(&neigh->expires, time_msec() +
++                         NEIGH_ENTRY_DEFAULT_IDLE_TIME_MS);
+     ovs_strlcpy(neigh->br_name, name, sizeof neigh->br_name);
+     cmap_insert(&table, &neigh->cmap_node, tnl_neigh_hash(&neigh->ip));
+     ovs_mutex_unlock(&mutex);
+@@ -144,12 +158,12 @@ tnl_arp_set(const char name[IFNAMSIZ], ovs_be32 dst,
+             const struct eth_addr mac)
+ {
+     struct in6_addr dst6 = in6_addr_mapped_ipv4(dst);
+-    tnl_neigh_set__(name, &dst6, mac);
++    tnl_neigh_set(name, &dst6, mac);
+ }
+ 
+ static int
+ tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc,
+-              const char name[IFNAMSIZ])
++              const char name[IFNAMSIZ], bool allow_update)
+ {
+     /* Snoop normal ARP replies and gratuitous ARP requests/replies only */
+     if (!is_arp(flow)
+@@ -159,13 +173,17 @@ tnl_arp_snoop(const struct flow *flow, struct flow_wildcards *wc,
+         return EINVAL;
+     }
+ 
+-    tnl_arp_set(name, FLOW_WC_GET_AND_MASK_WC(flow, wc, nw_src), flow->arp_sha);
++    memset(&wc->masks.nw_src, 0xff, sizeof wc->masks.nw_src);
++
++    if (allow_update) {
++        tnl_arp_set(name, flow->nw_src, flow->arp_sha);
++    }
+     return 0;
+ }
+ 
+ static int
+ tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
+-             const char name[IFNAMSIZ])
++             const char name[IFNAMSIZ], bool allow_update)
+ {
+     if (!is_nd(flow, wc) || flow->tp_src != htons(ND_NEIGHBOR_ADVERT)) {
+         return EINVAL;
+@@ -184,20 +202,22 @@ tnl_nd_snoop(const struct flow *flow, struct flow_wildcards *wc,
+     memset(&wc->masks.ipv6_dst, 0xff, sizeof wc->masks.ipv6_dst);
+     memset(&wc->masks.nd_target, 0xff, sizeof wc->masks.nd_target);
+ 
+-    tnl_neigh_set__(name, &flow->nd_target, flow->arp_tha);
++    if (allow_update) {
++        tnl_neigh_set(name, &flow->nd_target, flow->arp_tha);
++    }
+     return 0;
+ }
+ 
+ int
+ tnl_neigh_snoop(const struct flow *flow, struct flow_wildcards *wc,
+-                const char name[IFNAMSIZ])
++                const char name[IFNAMSIZ], bool allow_update)
+ {
+     int res;
+-    res = tnl_arp_snoop(flow, wc, name);
++    res = tnl_arp_snoop(flow, wc, name, allow_update);
+     if (res != EINVAL) {
+         return res;
+     }
+-    return tnl_nd_snoop(flow, wc, name);
++    return tnl_nd_snoop(flow, wc, name, allow_update);
+ }
+ 
+ void
+@@ -208,7 +228,7 @@ tnl_neigh_cache_run(void)
+ 
+     ovs_mutex_lock(&mutex);
+     CMAP_FOR_EACH(neigh, cmap_node, &table) {
+-        if (neigh->expires <= time_now()) {
++        if (tnl_neigh_expired(neigh)) {
+             tnl_neigh_delete(neigh);
+             changed = true;
+         }
+@@ -294,7 +314,7 @@ tnl_neigh_cache_add(struct unixctl_conn *conn, int argc OVS_UNUSED,
+         return;
+     }
+ 
+-    tnl_neigh_set__(br_name, &ip6, mac);
++    tnl_neigh_set(br_name, &ip6, mac);
+     unixctl_command_reply(conn, "OK");
+ }
+ 
+@@ -319,7 +339,7 @@ tnl_neigh_cache_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ 
+         ds_put_format(&ds, ETH_ADDR_FMT"   %s",
+                       ETH_ADDR_ARGS(neigh->mac), neigh->br_name);
+-        if (neigh->expires <= time_now()) {
++        if (tnl_neigh_expired(neigh)) {
+             ds_put_format(&ds, " STALE");
+         }
+         ds_put_char(&ds, '\n');
+diff --git a/lib/tnl-neigh-cache.h b/lib/tnl-neigh-cache.h
+index e4b42b0594..877bca3127 100644
+--- a/lib/tnl-neigh-cache.h
++++ b/lib/tnl-neigh-cache.h
+@@ -32,7 +32,9 @@
+ #include "util.h"
+ 
+ int tnl_neigh_snoop(const struct flow *flow, struct flow_wildcards *wc,
+-                    const char dev_name[IFNAMSIZ]);
++                    const char dev_name[IFNAMSIZ], bool allow_update);
++void tnl_neigh_set(const char name[IFNAMSIZ], const struct in6_addr *dst,
++                   const struct eth_addr mac);
+ int tnl_neigh_lookup(const char dev_name[IFNAMSIZ], const struct in6_addr *dst,
+                      struct eth_addr *mac);
+ void tnl_neigh_cache_init(void);
 diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
-index a426fcfeb6..970f78bb52 100644
+index a426fcfeb6..bb22d29034 100644
 --- a/ofproto/ofproto-dpif-xlate.c
 +++ b/ofproto/ofproto-dpif-xlate.c
-@@ -6177,11 +6177,32 @@ static void
+@@ -4097,7 +4097,21 @@ terminate_native_tunnel(struct xlate_ctx *ctx, struct flow *flow,
+             (flow->dl_type == htons(ETH_TYPE_ARP) ||
+              flow->nw_proto == IPPROTO_ICMPV6) &&
+              is_neighbor_reply_correct(ctx, flow)) {
+-            tnl_neigh_snoop(flow, wc, ctx->xbridge->name);
++            tnl_neigh_snoop(flow, wc, ctx->xbridge->name,
++                            ctx->xin->allow_side_effects);
++        } else if (*tnl_port != ODPP_NONE &&
++                   ctx->xin->allow_side_effects &&
++                   dl_type_is_ip_any(flow->dl_type)) {
++            struct eth_addr mac = flow->dl_src;
++            struct in6_addr s_ip6;
++
++            if (flow->dl_type == htons(ETH_TYPE_IP)) {
++                in6_addr_set_mapped_ipv4(&s_ip6, flow->nw_src);
++            } else {
++                s_ip6 = flow->ipv6_src;
++            }
++
++            tnl_neigh_set(ctx->xbridge->name, &s_ip6, mac);
+         }
+     }
+ 
+@@ -6177,11 +6191,32 @@ static void
  compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
                           bool is_last_action)
  {
@@ -1921,7 +2326,7 @@ index a426fcfeb6..970f78bb52 100644
 +    if (ofc->zone_src.field) {
 +        union mf_subvalue value;
 +        memset(&value, 0xff, sizeof(value));
-+
+ 
 +        zone = mf_get_subfield(&ofc->zone_src, &ctx->xin->flow);
 +        if (ctx->xin->frozen_state) {
 +            /* If the upcall is a resume of a recirculation, we only need to
@@ -1939,14 +2344,14 @@ index a426fcfeb6..970f78bb52 100644
 +    } else {
 +        zone = ofc->zone_imm;
 +    }
- 
++
 +    size_t ct_offset;
 +    ovs_u128 old_ct_label_mask = ctx->wc->masks.ct_label;
 +    uint32_t old_ct_mark_mask = ctx->wc->masks.ct_mark;
      /* Ensure that any prior actions are applied before composing the new
       * conntrack action. */
      xlate_commit_actions(ctx);
-@@ -6193,11 +6214,6 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
+@@ -6193,11 +6228,6 @@ compose_conntrack_action(struct xlate_ctx *ctx, struct ofpact_conntrack *ofc,
      do_xlate_actions(ofc->actions, ofpact_ct_get_action_len(ofc), ctx,
                       is_last_action, false);
  
@@ -1958,7 +2363,7 @@ index a426fcfeb6..970f78bb52 100644
  
      ct_offset = nl_msg_start_nested(ctx->odp_actions, OVS_ACTION_ATTR_CT);
      if (ofc->flags & NX_CT_F_COMMIT) {
-@@ -6333,6 +6349,7 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
+@@ -6333,6 +6363,7 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
       * then ctx->exit would be true. Reset to false so that we can
       * do flow translation for 'IF_LESS_EQUAL' case. finish_freezing()
       * would have taken care of Undoing the changes done for freeze. */
@@ -1966,7 +2371,7 @@ index a426fcfeb6..970f78bb52 100644
      ctx->exit = false;
  
      offset_attr = nl_msg_start_nested(
-@@ -6357,7 +6374,7 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
+@@ -6357,7 +6388,7 @@ xlate_check_pkt_larger(struct xlate_ctx *ctx,
      ctx->was_mpls = old_was_mpls;
      ctx->conntracked = old_conntracked;
      ctx->xin->flow = old_flow;
@@ -1975,7 +2380,7 @@ index a426fcfeb6..970f78bb52 100644
  }
  
  static void
-@@ -6738,6 +6755,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -6738,6 +6769,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
          return;
      }
  
@@ -1983,7 +2388,7 @@ index a426fcfeb6..970f78bb52 100644
      OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {
          struct ofpact_controller *controller;
          const struct ofpact_metadata *metadata;
-@@ -6752,7 +6770,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -6752,7 +6784,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
  
          recirc_for_mpls(a, ctx);
  
@@ -1992,7 +2397,7 @@ index a426fcfeb6..970f78bb52 100644
              /* Check if need to store the remaining actions for later
               * execution. */
              if (ctx->freezing) {
-@@ -7160,6 +7178,12 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
+@@ -7160,6 +7192,12 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
                                                               ofpacts_len);
              xlate_check_pkt_larger(ctx, ofpact_get_CHECK_PKT_LARGER(a),
                                     remaining_acts, remaining_acts_len);
@@ -4980,11 +5385,100 @@ index daa55dab7b..637271619f 100644
      ovsdb_idl_txn_commit_block(myTxn);
      ovsdb_idl_txn_destroy(myTxn);
      ovsdb_idl_get_initial_snapshot(idl);
+diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
+index 59723e63b8..c7665a1aeb 100644
+--- a/tests/tunnel-push-pop-ipv6.at
++++ b/tests/tunnel-push-pop-ipv6.at
+@@ -432,6 +432,42 @@ AT_CHECK([ovs-appctl dpif/dump-flows int-br | grep 'in_port(6081)'], [0], [dnl
+ tunnel(tun_id=0x7b,ipv6_src=2001:cafe::92,ipv6_dst=2001:cafe::88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=3,rule_cookie=0,controller_id=0,max_len=65535))
+ ])
+ 
++dnl Receive VXLAN with different MAC and verify that the neigh cache gets updated
++AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000f8bc1244cafe86dd60000000003a11402001cafe0000000000000000000000922001cafe000000000000000000000088c85312b5003abc700c00000300007b00ffffffffffff00000000000008004500001c0001000040117cce7f0000017f0000010035003500080172'])
++
++ovs-appctl time/warp 1000
++ovs-appctl time/warp 1000
++
++dnl Check VXLAN tunnel push
++AT_CHECK([ovs-ofctl add-flow int-br action=2])
++AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=36:b1:ee:7c:01:01,dst=36:b1:ee:7c:01:02),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
++AT_CHECK([tail -1 stdout], [0],
++  [Datapath actions: clone(tnl_push(tnl_port(4789),header(size=70,type=4,eth(dst=f8:bc:12:44:ca:fe,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=4789,csum=0xffff),vxlan(flags=0x8000000,vni=0x7b)),out_port(100)),1)
++])
++
++AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl
++2001:cafe::92                                 f8:bc:12:44:ca:fe   br0
++2001:cafe::93                                 f8:bc:12:44:34:b7   br0
++])
++
++dnl Restore and check the cache entries
++AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000f8bc124434b686dd60000000003a11402001cafe0000000000000000000000922001cafe000000000000000000000088c85312b5003abc700c00000300007b00ffffffffffff00000000000008004500001c0001000040117cce7f0000017f0000010035003500080172'])
++
++ovs-appctl time/warp 1000
++ovs-appctl time/warp 1000
++
++dnl Check VXLAN tunnel push
++AT_CHECK([ovs-ofctl add-flow int-br action=2])
++AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=36:b1:ee:7c:01:01,dst=36:b1:ee:7c:01:02),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
++AT_CHECK([tail -1 stdout], [0],
++  [Datapath actions: clone(tnl_push(tnl_port(4789),header(size=70,type=4,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=4789,csum=0xffff),vxlan(flags=0x8000000,vni=0x7b)),out_port(100)),1)
++])
++
++AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl
++2001:cafe::92                                 f8:bc:12:44:34:b6   br0
++2001:cafe::93                                 f8:bc:12:44:34:b7   br0
++])
++
+ ovs-appctl time/warp 10000
+ 
+ AT_CHECK([ovs-vsctl del-port int-br t3 \
 diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
-index 48c5de9d19..6364653975 100644
+index 48c5de9d19..6a597488e6 100644
 --- a/tests/tunnel-push-pop.at
 +++ b/tests/tunnel-push-pop.at
-@@ -595,6 +595,64 @@ OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 50540000000a5054000000091235 | wc
+@@ -522,6 +522,41 @@ AT_CHECK([ovs-appctl dpif/dump-flows int-br | grep 'in_port(6081)'], [0], [dnl
+ tunnel(tun_id=0x7b,src=1.1.2.92,dst=1.1.2.88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=2,rule_cookie=0,controller_id=0,max_len=65535))
+ ])
+ 
++dnl Receive VXLAN with different MAC and verify that the neigh cache gets updated
++AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000f8bc1244cafe08004500004e00010000401173e90101025c01010258c85312b5003a8cd40c00000300007b00ffffffffffff00000000000008004500001c0001000040117cce7f0000017f0000010035003500080172'])
++
++ovs-appctl time/warp 1000
++ovs-appctl time/warp 1000
++
++dnl Check VXLAN tunnel push
++AT_CHECK([ovs-ofctl add-flow int-br action=2])
++AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=36:b1:ee:7c:01:01,dst=36:b1:ee:7c:01:02),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
++AT_CHECK([tail -1 stdout], [0],
++  [Datapath actions: clone(tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=f8:bc:12:44:ca:fe,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0x8000000,vni=0x7b)),out_port(100)),1)
++])
++
++AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl
++1.1.2.92                                      f8:bc:12:44:ca:fe   br0
++1.1.2.93                                      f8:bc:12:44:34:b7   br0
++])
++
++dnl Restore and check the cache entries
++AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000f8bc124434b608004500004e00010000401173e90101025c01010258c85312b5003a8cd40c00000300007b00ffffffffffff00000000000008004500001c0001000040117cce7f0000017f0000010035003500080172'])
++
++ovs-appctl time/warp 1000
++ovs-appctl time/warp 1000
++
++dnl Check VXLAN tunnel push
++AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=36:b1:ee:7c:01:01,dst=36:b1:ee:7c:01:02),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
++AT_CHECK([tail -1 stdout], [0],
++  [Datapath actions: clone(tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0x8000000,vni=0x7b)),out_port(100)),1)
++])
++
++AT_CHECK([ovs-appctl tnl/neigh/show | tail -n+3 | sort], [0], [dnl
++1.1.2.92                                      f8:bc:12:44:34:b6   br0
++1.1.2.93                                      f8:bc:12:44:34:b7   br0
++])
++
+ ovs-appctl time/warp 10000
+ 
+ AT_CHECK([ovs-vsctl del-port int-br t3 \
+@@ -595,6 +630,64 @@ OVS_WAIT_UNTIL([test `ovs-pcap p0.pcap | grep 50540000000a5054000000091235 | wc
  OVS_VSWITCHD_STOP
  AT_CLEANUP
  
diff --git a/SPECS/openvswitch2.16.spec b/SPECS/openvswitch2.16.spec
index b2851c7..a9aaec5 100644
--- a/SPECS/openvswitch2.16.spec
+++ b/SPECS/openvswitch2.16.spec
@@ -57,7 +57,7 @@ Summary: Open vSwitch
 Group: System Environment/Daemons daemon/database/utilities
 URL: http://www.openvswitch.org/
 Version: 2.16.0
-Release: 33%{?dist}
+Release: 36%{?dist}
 
 # Nearly all of openvswitch is ASL 2.0.  The bugtool is LGPLv2+, and the
 # lib/sflow*.[ch] files are SISSL
@@ -699,6 +699,29 @@ exit 0
 %endif
 
 %changelog
+* Thu Jan 13 2022 Open vSwitch CI <ovs-ci@redhat.com> - 2.16.0-36
+- Merging upstream branch-2.16 [RH git: edae801e00]
+    Commit list:
+    ba7fffb832 dpif-netdev: Improve loading of packet data for undersized packets.
+
+
+* Sat Dec 18 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.16.0-35
+- Merging upstream branch-2.16 [RH git: 6ad0375ff5]
+    Commit list:
+    2595b7b3d1 Prepare for 2.16.3.
+    6caaae525c Set release date for 2.16.2.
+    443e3657d7 ofproto-dpif-xlate: Snoop ingress packets and update neigh cache if needed.
+    75d2ef9a60 tnl-neigh-cache: Do not refresh the entry while revalidating.
+    5d88836566 tnl-neigh-cache: Read/write expires atomically.
+    fb42c99c15 dpif-netdev: Improve handling of IP/TCP in avx512 mfex.
+
+
+* Thu Dec 09 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.16.0-34
+- Merging upstream branch-2.16 [RH git: 07b9bf085a]
+    Commit list:
+    f42c484445 compat: handle NF_REPEAT error on nf_conntrack_in.
+
+
 * Mon Dec 06 2021 Open vSwitch CI <ovs-ci@redhat.com> - 2.16.0-33
 - Merging upstream branch-2.16 [RH git: 8708b55152]
     Commit list: