diff --git a/.openvswitch.metadata b/.openvswitch.metadata
index 0db19ca..8e71823 100644
--- a/.openvswitch.metadata
+++ b/.openvswitch.metadata
@@ -1,5 +1,5 @@
-002450621b33c5690060345b0aac25bc2426d675 SOURCES/docutils-0.12.tar.gz
-435b0b3a5da6d7417d318050e5b50ac400354c60 SOURCES/dpdk-19.11.tar.xz
-0c5f78212173d2cac286f8f78aa95ebdea9e2444 SOURCES/openvswitch-2.13.0.tar.gz
-d34f96421a86004aa5d26ecf975edefd09f948b1 SOURCES/Pygments-1.4.tar.gz
-6beb30f18ffac3de7689b7fd63e9a8a7d9c8df3a SOURCES/Sphinx-1.1.3.tar.gz
+002450621b33c5690060345b0aac25bc2426d675  SOURCES/docutils-0.12.tar.gz
+0c5f78212173d2cac286f8f78aa95ebdea9e2444  SOURCES/openvswitch-2.13.0.tar.gz
+d34f96421a86004aa5d26ecf975edefd09f948b1  SOURCES/Pygments-1.4.tar.gz
+6beb30f18ffac3de7689b7fd63e9a8a7d9c8df3a  SOURCES/Sphinx-1.1.3.tar.gz
+435b0b3a5da6d7417d318050e5b50ac400354c60  SOURCES/dpdk-19.11.tar.xz
diff --git a/SOURCES/openvswitch-2.13.0.patch b/SOURCES/openvswitch-2.13.0.patch
index 6537811..23eecc4 100644
--- a/SOURCES/openvswitch-2.13.0.patch
+++ b/SOURCES/openvswitch-2.13.0.patch
@@ -1,6 +1,6 @@
 diff --git a/.ci/linux-build.sh b/.ci/linux-build.sh
 new file mode 100755
-index 0000000000..ec0b40e472
+index 0000000000..c1cf85d7d9
 --- /dev/null
 +++ b/.ci/linux-build.sh
 @@ -0,0 +1,244 @@
@@ -188,7 +188,7 @@ index 0000000000..ec0b40e472
 +
 +if [ "$DPDK" ] || [ "$DPDK_SHARED" ]; then
 +    if [ -z "$DPDK_VER" ]; then
-+        DPDK_VER="19.11.2"
++        DPDK_VER="19.11.6"
 +    fi
 +    install_dpdk $DPDK_VER
 +    # Enable pdump support in OVS.
@@ -224,7 +224,7 @@ index 0000000000..ec0b40e472
 +    configure_ovs
 +
 +    export DISTCHECK_CONFIGURE_FLAGS="$OPTS"
-+    if ! make distcheck CFLAGS="${CFLAGS_FOR_OVS}" \
++    if ! make distcheck -j4 CFLAGS="${CFLAGS_FOR_OVS}" \
 +         TESTSUITEFLAGS=-j4 RECHECK=yes; then
 +        # testsuite.log is necessary for debugging.
 +        cat */_build/sub/tests/testsuite.log
@@ -344,14 +344,16 @@ index 0000000000..b6447aba1b
 +set -ev
 +pip3 install --user --upgrade docutils
 diff --git a/.cirrus.yml b/.cirrus.yml
-index 1b32f55d65..263c2cd7ed 100644
+index 1b32f55d65..2caf36b85c 100644
 --- a/.cirrus.yml
 +++ b/.cirrus.yml
-@@ -3,7 +3,7 @@ freebsd_build_task:
+@@ -2,8 +2,8 @@ freebsd_build_task:
+ 
    freebsd_instance:
      matrix:
-       image_family: freebsd-12-1-snap
+-      image_family: freebsd-12-1-snap
 -      image_family: freebsd-11-3-snap
++      image_family: freebsd-12-2-snap
 +      image_family: freebsd-11-4-snap
      cpu: 4
      memory: 8G
@@ -366,7 +368,7 @@ index 1b32f55d65..263c2cd7ed 100644
    configure_script:
 diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
 new file mode 100644
-index 0000000000..fe76a866ea
+index 0000000000..8849659979
 --- /dev/null
 +++ b/.github/workflows/build-and-test.yml
 @@ -0,0 +1,205 @@
@@ -505,7 +507,7 @@ index 0000000000..fe76a866ea
 +        key:  ${{ env.matrix_key }}-${{ env.ci_key }}
 +
 +    - name: update APT cache
-+      run:  sudo apt update
++      run:  sudo apt update || true
 +    - name: install common dependencies
 +      if:   matrix.deb_package == ''
 +      run:  sudo apt install -y ${{ env.dependencies }}
@@ -612,7 +614,7 @@ index fe3935fca2..4c8772f63a 100644
  ankur dwivedi                   ankurengg2003@gmail.com
  chen zhang                      3zhangchen9211@gmail.com
 diff --git a/Documentation/faq/releases.rst b/Documentation/faq/releases.rst
-index 6702c58a2b..41e1315a4c 100644
+index 6702c58a2b..4a0dcac495 100644
 --- a/Documentation/faq/releases.rst
 +++ b/Documentation/faq/releases.rst
 @@ -67,9 +67,10 @@ Q: What Linux kernel versions does each Open vSwitch release work with?
@@ -663,9 +665,9 @@ index 6702c58a2b..41e1315a4c 100644
 -    ============ =======
 +    2.9.x        17.11.10
 +    2.10.x       17.11.10
-+    2.11.x       18.11.9
-+    2.12.x       18.11.9
-+    2.13.x       19.11.2
++    2.11.x       18.11.11
++    2.12.x       18.11.11
++    2.13.x       19.11.6
 +    ============ ========
  
  Q: Are all the DPDK releases that OVS versions work with maintained?
@@ -690,7 +692,7 @@ index 5a314cc60a..f2039595e7 100644
  Email Subject
  -------------
 diff --git a/Documentation/intro/install/dpdk.rst b/Documentation/intro/install/dpdk.rst
-index dbf88ec43f..86ee19d4c4 100644
+index dbf88ec43f..050e5544b3 100644
 --- a/Documentation/intro/install/dpdk.rst
 +++ b/Documentation/intro/install/dpdk.rst
 @@ -42,7 +42,7 @@ Build requirements
@@ -698,7 +700,7 @@ index dbf88ec43f..86ee19d4c4 100644
  vSwitch with DPDK will require the following:
  
 -- DPDK 19.11
-+- DPDK 19.11.2
++- DPDK 19.11.6
  
  - A `DPDK supported NIC`_
  
@@ -709,9 +711,9 @@ index dbf88ec43f..86ee19d4c4 100644
 -       $ wget https://fast.dpdk.org/rel/dpdk-19.11.tar.xz
 -       $ tar xf dpdk-19.11.tar.xz
 -       $ export DPDK_DIR=/usr/src/dpdk-19.11
-+       $ wget https://fast.dpdk.org/rel/dpdk-19.11.2.tar.xz
-+       $ tar xf dpdk-19.11.2.tar.xz
-+       $ export DPDK_DIR=/usr/src/dpdk-stable-19.11.2
++       $ wget https://fast.dpdk.org/rel/dpdk-19.11.6.tar.xz
++       $ tar xf dpdk-19.11.6.tar.xz
++       $ export DPDK_DIR=/usr/src/dpdk-stable-19.11.6
         $ cd $DPDK_DIR
  
  #. (Optional) Configure DPDK as a shared library
@@ -744,8 +746,43 @@ index 38e52c8deb..55a98e2b0e 100644
  Link State Change (LSC) detection configuration
  -----------------------------------------------
  
+diff --git a/Documentation/topics/dpdk/qos.rst b/Documentation/topics/dpdk/qos.rst
+index 103495415a..a98ec672fc 100644
+--- a/Documentation/topics/dpdk/qos.rst
++++ b/Documentation/topics/dpdk/qos.rst
+@@ -69,22 +69,24 @@ to prioritize certain traffic over others at a port level.
+ 
+ For example, the following configuration will limit the traffic rate at a
+ port level to a maximum of 2000 packets a second (64 bytes IPv4 packets).
+-100pps as CIR (Committed Information Rate) and 1000pps as EIR (Excess
+-Information Rate). High priority traffic is routed to queue 10, which marks
++1000pps as CIR (Committed Information Rate) and 1000pps as EIR (Excess
++Information Rate). CIR and EIR are measured in bytes without Ethernet header.
++As a result, 1000pps means (64-byte - 14-byte) * 1000 = 50,000 in the
++configuration below. High priority traffic is routed to queue 10, which marks
+ all traffic as CIR, i.e. Green. All low priority traffic, queue 20, is
+ marked as EIR, i.e. Yellow::
+ 
+     $ ovs-vsctl --timeout=5 set port dpdk1 qos=@myqos -- \
+         --id=@myqos create qos type=trtcm-policer \
+-        other-config:cir=52000 other-config:cbs=2048 \
+-        other-config:eir=52000 other-config:ebs=2048  \
++        other-config:cir=50000 other-config:cbs=2048 \
++        other-config:eir=50000 other-config:ebs=2048  \
+         queues:10=@dpdk1Q10 queues:20=@dpdk1Q20 -- \
+          --id=@dpdk1Q10 create queue \
+-          other-config:cir=41600000 other-config:cbs=2048 \
++          other-config:cir=100000 other-config:cbs=2048 \
+           other-config:eir=0 other-config:ebs=0 -- \
+          --id=@dpdk1Q20 create queue \
+            other-config:cir=0 other-config:cbs=0 \
+-           other-config:eir=41600000 other-config:ebs=2048 \
++           other-config:eir=50000 other-config:ebs=2048
+ 
+ This configuration accomplishes that the high priority traffic has a
+ guaranteed bandwidth egressing the ports at CIR (1000pps), but it can also
 diff --git a/Documentation/topics/dpdk/vhost-user.rst b/Documentation/topics/dpdk/vhost-user.rst
-index c6c6fd8bde..4bc5aef59d 100644
+index c6c6fd8bde..d0201151a0 100644
 --- a/Documentation/topics/dpdk/vhost-user.rst
 +++ b/Documentation/topics/dpdk/vhost-user.rst
 @@ -392,9 +392,9 @@ To begin, instantiate a guest as described in :ref:`dpdk-vhost-user` or
@@ -755,9 +792,9 @@ index c6c6fd8bde..4bc5aef59d 100644
 -    $ wget https://fast.dpdk.org/rel/dpdk-19.11.tar.xz
 -    $ tar xf dpdk-19.11.tar.xz
 -    $ export DPDK_DIR=/root/dpdk/dpdk-19.11
-+    $ wget https://fast.dpdk.org/rel/dpdk-19.11.2.tar.xz
-+    $ tar xf dpdk-19.11.2.tar.xz
-+    $ export DPDK_DIR=/root/dpdk/dpdk-stable-19.11.2
++    $ wget https://fast.dpdk.org/rel/dpdk-19.11.6.tar.xz
++    $ tar xf dpdk-19.11.6.tar.xz
++    $ export DPDK_DIR=/root/dpdk/dpdk-stable-19.11.6
      $ export DPDK_TARGET=x86_64-native-linuxapp-gcc
      $ export DPDK_BUILD=$DPDK_DIR/$DPDK_TARGET
      $ cd $DPDK_DIR
@@ -900,12 +937,31 @@ index b279303d18..b3b56cd50e 100644
  	boot.sh \
  	poc/builders/Vagrantfile \
 diff --git a/NEWS b/NEWS
-index dab94e924d..86d6e0a3d8 100644
+index dab94e924d..32ec919d13 100644
 --- a/NEWS
 +++ b/NEWS
-@@ -1,3 +1,30 @@
-+v2.13.2 - xx xxx xxxx
+@@ -1,3 +1,49 @@
++v2.13.4 - xx xxx xxxx
++---------------------
++   - DPDK:
++     * OVS validated with DPDK 19.11.6. It is recommended to use this version
++       until further releases.
++   - ovs-ctl:
++     * New option '--no-record-hostname' to disable hostname configuration
++       in ovsdb on startup.
++     * New command 'record-hostname-if-not-set' to update hostname in ovsdb.
++
++v2.13.3 - 10 Feb 2021
 +---------------------
++   - Bug fixes
++   - Security:
++     * Fixed packet parsing vulnerability CVE-2020-35498.
++
++v2.13.2 - 13 Jan 2021
++---------------------
++   - Bug fixes
++   - LLDP:
++     * Security fixes for CVE-2015-8011 and CVE-2020-27827.
 +   - IPsec:
 +     * Fixed support of strongswan 5.7+ in ovs-monitor-ipsec.
 +     * Add option '--no-cleanup' to allow ovs-monitor-ipsec to stop without
@@ -934,7 +990,7 @@ index dab94e924d..86d6e0a3d8 100644
  v2.13.0 - 14 Feb 2020
  ---------------------
     - OVN:
-@@ -43,6 +70,9 @@ v2.13.0 - 14 Feb 2020
+@@ -43,6 +89,9 @@ v2.13.0 - 14 Feb 2020
     - 'ovs-appctl dpctl/dump-flows' can now show offloaded=partial for
       partially offloaded flows, dp:dpdk for fully offloaded by dpdk, and
       type filter supports new filters: "dpdk" and "partially-offloaded".
@@ -944,7 +1000,7 @@ index dab94e924d..86d6e0a3d8 100644
  
  v2.12.0 - 03 Sep 2019
  ---------------------
-@@ -117,9 +147,6 @@ v2.12.0 - 03 Sep 2019
+@@ -117,9 +166,6 @@ v2.12.0 - 03 Sep 2019
       * Add support for conntrack zone-based timeout policy.
     - 'ovs-dpctl dump-flows' is no longer suitable for dumping offloaded flows.
       'ovs-appctl dpctl/dump-flows' should be used instead.
@@ -970,7 +1026,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..12fd6c4a51 100644
+index c1470ccc6b..f4fd56e620 100644
 --- a/acinclude.m4
 +++ b/acinclude.m4
 @@ -250,6 +250,18 @@ AC_DEFUN([OVS_CHECK_LINUX_SCTP_CT], [
@@ -1000,7 +1056,24 @@ index c1470ccc6b..12fd6c4a51 100644
        AC_CHECK_DECL([RTE_IBVERBS_LINK_DLOPEN], [], [dnl not found
          OVS_FIND_DEPENDENCY([mlx5dv_create_wq], [mlx5], [libmlx5])
          OVS_FIND_DEPENDENCY([verbs_init_cq], [ibverbs], [libibverbs])
-@@ -567,9 +578,14 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
+@@ -420,6 +431,16 @@ AC_DEFUN([OVS_CHECK_DPDK], [
+     if test "$DPDK_AUTO_DISCOVER" = "false"; then
+       OVS_LDFLAGS="$OVS_LDFLAGS -L$DPDK_LIB_DIR"
+     fi
++    # Stripping out possible instruction set specific configuration that DPDK
++    # forces in pkg-config since this could override user-specified options.
++    # It's enough to have -mssse3 to build with DPDK headers.
++    DPDK_INCLUDE=$(echo "$DPDK_INCLUDE" | sed 's/-march=[[^ ]]*//g')
++    # Also stripping out '-mno-avx512f'.  Support for AVX512 will be disabled
++    # if OVS will detect that it's broken.  OVS could be built with a
++    # completely different toolchain that correctly supports AVX512, flags
++    # forced by DPDK only breaks our feature detection mechanism and leads to
++    # build failures: https://github.com/openvswitch/ovs-issues/issues/201
++    DPDK_INCLUDE=$(echo "$DPDK_INCLUDE" | sed 's/-mno-avx512f//g')
+     OVS_CFLAGS="$OVS_CFLAGS $DPDK_INCLUDE"
+     OVS_ENABLE_OPTION([-mssse3])
+ 
+@@ -567,9 +588,14 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
    OVS_GREP_IFELSE([$KSRC/include/net/ip6_fib.h], [rt6_get_cookie],
                    [OVS_DEFINE([HAVE_RT6_GET_COOKIE])])
  
@@ -1015,7 +1088,7 @@ index c1470ccc6b..12fd6c4a51 100644
  
    OVS_GREP_IFELSE([$KSRC/include/linux/err.h], [ERR_CAST])
    OVS_GREP_IFELSE([$KSRC/include/linux/err.h], [IS_ERR_OR_NULL])
-@@ -765,6 +781,10 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
+@@ -765,6 +791,10 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
                    [prandom_u32[[\(]]],
                    [OVS_DEFINE([HAVE_PRANDOM_U32])])
    OVS_GREP_IFELSE([$KSRC/include/linux/random.h], [prandom_u32_max])
@@ -1026,7 +1099,7 @@ index c1470ccc6b..12fd6c4a51 100644
  
    OVS_GREP_IFELSE([$KSRC/include/net/rtnetlink.h], [get_link_net])
    OVS_GREP_IFELSE([$KSRC/include/net/rtnetlink.h], [name_assign_type])
-@@ -918,8 +938,6 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
+@@ -918,8 +948,6 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
  
    OVS_GREP_IFELSE([$KSRC/include/net/sock.h], [sk_no_check_tx])
    OVS_GREP_IFELSE([$KSRC/include/linux/udp.h], [no_check6_tx])
@@ -1035,7 +1108,7 @@ index c1470ccc6b..12fd6c4a51 100644
    OVS_FIND_PARAM_IFELSE([$KSRC/include/net/protocol.h],
                          [udp_add_offload], [net],
                          [OVS_DEFINE([HAVE_UDP_ADD_OFFLOAD_TAKES_NET])])
-@@ -1294,11 +1312,11 @@ AC_DEFUN([OVS_ENABLE_SPARSE],
+@@ -1294,11 +1322,11 @@ AC_DEFUN([OVS_ENABLE_SPARSE],
  
  dnl OVS_CTAGS_IDENTIFIERS
  dnl
@@ -1050,8 +1123,21 @@ index c1470ccc6b..12fd6c4a51 100644
  
  dnl OVS_PTHREAD_SET_NAME
  dnl
+diff --git a/build-aux/dist-docs b/build-aux/dist-docs
+index f6b88ca2d0..9429702db9 100755
+--- a/build-aux/dist-docs
++++ b/build-aux/dist-docs
+@@ -43,7 +43,7 @@ rm -rf $distdir
+ mkdir $distdir
+ 
+ # Install manpages.
+-${MAKE-make} install-man mandir="$abs_distdir"/man
++${MAKE-make} install-man install-man-rst mandir="$abs_distdir"/man
+ (cd $distdir && mv `find man -type f` . && rm -rf man)
+ manpages=`cd $distdir && echo *`
+ 
 diff --git a/configure.ac b/configure.ac
-index 92b52f6712..72aa36b443 100644
+index 92b52f6712..34276bcbe7 100644
 --- a/configure.ac
 +++ b/configure.ac
 @@ -13,7 +13,7 @@
@@ -1059,7 +1145,7 @@ index 92b52f6712..72aa36b443 100644
  
  AC_PREREQ(2.63)
 -AC_INIT(openvswitch, 2.13.0, bugs@openvswitch.org)
-+AC_INIT(openvswitch, 2.13.2, bugs@openvswitch.org)
++AC_INIT(openvswitch, 2.13.4, bugs@openvswitch.org)
  AC_CONFIG_SRCDIR([datapath/datapath.c])
  AC_CONFIG_MACRO_DIR([m4])
  AC_CONFIG_AUX_DIR([build-aux])
@@ -1537,15 +1623,27 @@ index 23118e8b63..05ccfb9288 100644
  	*saddr = fl6.saddr;
  	if (use_cache)
 diff --git a/debian/changelog b/debian/changelog
-index 8e075bc98b..d803cf10d1 100644
+index 8e075bc98b..f63d5cc46a 100644
 --- a/debian/changelog
 +++ b/debian/changelog
-@@ -1,3 +1,15 @@
+@@ -1,3 +1,27 @@
++openvswitch (2.13.4-1) unstable; urgency=low
++   [ Open vSwitch team ]
++   * New upstream version
++
++ -- Open vSwitch team <dev@openvswitch.org>  Wed, 10 Feb 2021 16:07:28 +0100
++
++openvswitch (2.13.3-1) unstable; urgency=low
++   [ Open vSwitch team ]
++   * New upstream version
++
++ -- Open vSwitch team <dev@openvswitch.org>  Wed, 10 Feb 2021 16:07:28 +0100
++
 +openvswitch (2.13.2-1) unstable; urgency=low
 +   [ Open vSwitch team ]
 +   * New upstream version
 +
-+ -- Open vSwitch team <dev@openvswitch.org>  Thu, 30 Jul 2020 00:25:23 +0200
++ -- Open vSwitch team <dev@openvswitch.org>  Wed, 13 Jan 2021 11:26:36 -0500
 +
 +openvswitch (2.13.1-1) unstable; urgency=low
 +   [ Open vSwitch team]
@@ -39581,6 +39679,44 @@ index d1bd4aa12a..f646a8f742 100644
  };
  
  enum {
+diff --git a/lib/conntrack-icmp.c b/lib/conntrack-icmp.c
+index 63246f0124..63ddd8038b 100644
+--- a/lib/conntrack-icmp.c
++++ b/lib/conntrack-icmp.c
+@@ -50,10 +50,16 @@ icmp_conn_update(struct conntrack *ct, struct conn *conn_,
+                  struct dp_packet *pkt OVS_UNUSED, bool reply, long long now)
+ {
+     struct conn_icmp *conn = conn_icmp_cast(conn_);
+-    conn->state = reply ? ICMPS_REPLY : ICMPS_FIRST;
+-    conn_update_expiration(ct, &conn->up, icmp_timeouts[conn->state], now);
++    enum ct_update_res ret = CT_UPDATE_VALID;
++
++    if (reply && conn->state == ICMPS_FIRST) {
++       conn->state = ICMPS_REPLY;
++    } else if (conn->state == ICMPS_FIRST) {
++        ret = CT_UPDATE_VALID_NEW;
++    }
+ 
+-    return CT_UPDATE_VALID;
++    conn_update_expiration(ct, &conn->up, icmp_timeouts[conn->state], now);
++    return ret;
+ }
+ 
+ static bool
+diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h
+index 9a8ca39101..cd6c4bfee9 100644
+--- a/lib/conntrack-private.h
++++ b/lib/conntrack-private.h
+@@ -59,6 +59,9 @@ struct conn_key {
+     uint8_t nw_proto;
+ };
+ 
++/* Verify that nw_proto stays uint8_t as it's used to index into l4_protos[] */
++BUILD_ASSERT_DECL(MEMBER_SIZEOF(struct conn_key, nw_proto) == sizeof(uint8_t));
++
+ /* This is used for alg expectations; an expectation is a
+  * context created in preparation for establishing a data
+  * connection. The expectation is created by the control
 diff --git a/lib/conntrack-tcp.c b/lib/conntrack-tcp.c
 index 416cb769d2..47261c7551 100644
 --- a/lib/conntrack-tcp.c
@@ -39595,10 +39731,51 @@ index 416cb769d2..47261c7551 100644
      }
  
 diff --git a/lib/conntrack.c b/lib/conntrack.c
-index ff5a89457c..bb98395cd2 100644
+index ff5a89457c..a673678fe5 100644
 --- a/lib/conntrack.c
 +++ b/lib/conntrack.c
-@@ -813,7 +813,7 @@ static void
+@@ -143,12 +143,7 @@ detect_ftp_ctl_type(const struct conn_lookup_ctx *ctx,
+ static void
+ expectation_clean(struct conntrack *ct, const struct conn_key *master_key);
+ 
+-static struct ct_l4_proto *l4_protos[] = {
+-    [IPPROTO_TCP] = &ct_proto_tcp,
+-    [IPPROTO_UDP] = &ct_proto_other,
+-    [IPPROTO_ICMP] = &ct_proto_icmp4,
+-    [IPPROTO_ICMPV6] = &ct_proto_icmp6,
+-};
++static struct ct_l4_proto *l4_protos[UINT8_MAX + 1];
+ 
+ static void
+ handle_ftp_ctl(struct conntrack *ct, const struct conn_lookup_ctx *ctx,
+@@ -296,6 +291,7 @@ ct_print_conn_info(const struct conn *c, const char *log_msg,
+ struct conntrack *
+ conntrack_init(void)
+ {
++    static struct ovsthread_once setup_l4_once = OVSTHREAD_ONCE_INITIALIZER;
+     struct conntrack *ct = xzalloc(sizeof *ct);
+ 
+     ovs_rwlock_init(&ct->resources_lock);
+@@ -322,6 +318,18 @@ conntrack_init(void)
+     ct->clean_thread = ovs_thread_create("ct_clean", clean_thread_main, ct);
+     ct->ipf = ipf_init();
+ 
++    /* Initialize the l4 protocols. */
++    if (ovsthread_once_start(&setup_l4_once)) {
++        for (int i = 0; i < ARRAY_SIZE(l4_protos); i++) {
++            l4_protos[i] = &ct_proto_other;
++        }
++        /* IPPROTO_UDP uses ct_proto_other, so no need to initialize it. */
++        l4_protos[IPPROTO_TCP] = &ct_proto_tcp;
++        l4_protos[IPPROTO_ICMP] = &ct_proto_icmp4;
++        l4_protos[IPPROTO_ICMPV6] = &ct_proto_icmp6;
++
++        ovsthread_once_done(&setup_l4_once);
++    }
+     return ct;
+ }
+ 
+@@ -813,7 +821,7 @@ static void
  reverse_nat_packet(struct dp_packet *pkt, const struct conn *conn)
  {
      char *tail = dp_packet_tail(pkt);
@@ -39607,7 +39784,7 @@ index ff5a89457c..bb98395cd2 100644
      struct conn_key inner_key;
      const char *inner_l4 = NULL;
      uint16_t orig_l3_ofs = pkt->l3_ofs;
-@@ -1277,6 +1277,11 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
+@@ -1277,6 +1285,11 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
              const struct nat_action_info_t *nat_action_info,
              ovs_be16 tp_src, ovs_be16 tp_dst, const char *helper)
  {
@@ -39619,7 +39796,7 @@ index ff5a89457c..bb98395cd2 100644
      bool create_new_conn = false;
      conn_key_lookup(ct, &ctx->key, ctx->hash, now, &ctx->conn, &ctx->reply);
      struct conn *conn = ctx->conn;
-@@ -1300,9 +1305,10 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
+@@ -1300,9 +1313,10 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
              conn_key_lookup(ct, &ctx->key, hash, now, &conn, &ctx->reply);
  
              if (!conn) {
@@ -39632,6 +39809,30 @@ index ff5a89457c..bb98395cd2 100644
                  free(log_msg);
                  return;
              }
+@@ -1964,9 +1978,10 @@ extract_l4(struct conn_key *key, const void *data, size_t size, bool *related,
+         return (!related || check_l4_icmp6(key, data, size, l3,
+                 validate_checksum))
+                && extract_l4_icmp6(key, data, size, related);
+-    } else {
+-        return false;
+     }
++
++    /* For all other protocols we do not have L4 keys, so keep them zero. */
++    return true;
+ }
+ 
+ static bool
+@@ -2249,8 +2264,8 @@ nat_select_range_tuple(struct conntrack *ct, const struct conn *conn,
+               conn->nat_info->nat_action & NAT_ACTION_SRC_PORT
+           ? true : false;
+     union ct_addr first_addr = ct_addr;
+-    bool pat_enabled = conn->key.nw_proto != IPPROTO_ICMP &&
+-                       conn->key.nw_proto != IPPROTO_ICMPV6;
++    bool pat_enabled = conn->key.nw_proto == IPPROTO_TCP ||
++                       conn->key.nw_proto == IPPROTO_UDP;
+ 
+     while (true) {
+         if (conn->nat_info->nat_action & NAT_ACTION_SRC) {
 diff --git a/lib/dp-packet.h b/lib/dp-packet.h
 index 9f8991faad..45655af461 100644
 --- a/lib/dp-packet.h
@@ -39674,7 +39875,7 @@ index 9f8991faad..45655af461 100644
      ovs_assert(pad_size <= dp_packet_size(b));
      b->l2_pad_size = pad_size;
 diff --git a/lib/dpctl.c b/lib/dpctl.c
-index db2b1f8961..09ae97f25c 100644
+index db2b1f8961..36038a13d8 100644
 --- a/lib/dpctl.c
 +++ b/lib/dpctl.c
 @@ -1031,7 +1031,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
@@ -39686,6 +39887,27 @@ index db2b1f8961..09ae97f25c 100644
      }
      determine_dpif_flow_dump_types(&dump_types, &dpif_dump_types);
  
+@@ -2502,15 +2502,16 @@ static const struct dpctl_command all_commands[] = {
+     { "del-if", "dp iface...", 2, INT_MAX, dpctl_del_if, DP_RW },
+     { "set-if", "dp iface...", 2, INT_MAX, dpctl_set_if, DP_RW },
+     { "dump-dps", "", 0, 0, dpctl_dump_dps, DP_RO },
+-    { "show", "[dp...]", 0, INT_MAX, dpctl_show, DP_RO },
+-    { "dump-flows", "[dp] [filter=..] [type=..]",
+-      0, 3, dpctl_dump_flows, DP_RO },
++    { "show", "[-s] [dp...]", 0, INT_MAX, dpctl_show, DP_RO },
++    { "dump-flows", "[-m] [--names] [dp] [filter=..] [type=..]",
++      0, 5, dpctl_dump_flows, DP_RO },
+     { "add-flow", "[dp] flow actions", 2, 3, dpctl_add_flow, DP_RW },
+     { "mod-flow", "[dp] flow actions", 2, 3, dpctl_mod_flow, DP_RW },
+     { "get-flow", "[dp] ufid", 1, 2, dpctl_get_flow, DP_RO },
+     { "del-flow", "[dp] flow", 1, 2, dpctl_del_flow, DP_RW },
+     { "del-flows", "[dp]", 0, 1, dpctl_del_flows, DP_RW },
+-    { "dump-conntrack", "[dp] [zone=N]", 0, 2, dpctl_dump_conntrack, DP_RO },
++    { "dump-conntrack", "[-m] [-s] [dp] [zone=N]",
++      0, 4, dpctl_dump_conntrack, DP_RO },
+     { "flush-conntrack", "[dp] [zone=N] [ct-tuple]", 0, 3,
+       dpctl_flush_conntrack, DP_RW },
+     { "ct-stats-show", "[dp] [zone=N]",
 diff --git a/lib/dpif-netdev-private.h b/lib/dpif-netdev-private.h
 index 68c33a0f96..9b251f81fa 100644
 --- a/lib/dpif-netdev-private.h
@@ -39699,7 +39921,7 @@ index 68c33a0f96..9b251f81fa 100644
   * 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/lib/dpif-netdev.c b/lib/dpif-netdev.c
-index d393aab5e3..1d6b54ff16 100644
+index d393aab5e3..888325e5f2 100644
 --- a/lib/dpif-netdev.c
 +++ b/lib/dpif-netdev.c
 @@ -83,9 +83,9 @@
@@ -39905,7 +40127,23 @@ index d393aab5e3..1d6b54ff16 100644
      flow->dead = false;
      flow->batch = NULL;
      flow->mark = INVALID_FLOW_MARK;
-@@ -3875,11 +3970,12 @@ dpif_netdev_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops,
+@@ -3506,6 +3601,15 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
+         return error;
+     }
+ 
++    if (match.wc.masks.in_port.odp_port != ODPP_NONE) {
++        static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
++
++        VLOG_ERR_RL(&rl, "failed to put%s flow: in_port is not an exact match",
++                    (put->flags & DPIF_FP_CREATE) ? "[create]"
++                    : (put->flags & DPIF_FP_MODIFY) ? "[modify]" : "[zero]");
++        return EINVAL;
++    }
++
+     if (put->ufid) {
+         ufid = *put->ufid;
+     } else {
+@@ -3875,11 +3979,12 @@ dpif_netdev_operate(struct dpif *dpif, struct dpif_op **ops, size_t n_ops,
  
  /* Enable or Disable PMD auto load balancing. */
  static void
@@ -39919,7 +40157,7 @@ index d393aab5e3..1d6b54ff16 100644
  
      bool enable_alb = false;
      bool multi_rxq = false;
-@@ -3906,18 +4002,24 @@ set_pmd_auto_lb(struct dp_netdev *dp)
+@@ -3906,18 +4011,24 @@ set_pmd_auto_lb(struct dp_netdev *dp)
      enable_alb = enable_alb && pmd_rxq_assign_cyc &&
                      pmd_alb->auto_lb_requested;
  
@@ -39948,7 +40186,7 @@ index d393aab5e3..1d6b54ff16 100644
  }
  
  /* Applies datapath configuration from the database. Some of the changes are
-@@ -3935,6 +4037,9 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
+@@ -3935,6 +4046,9 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
      uint32_t insert_min, cur_min;
      uint32_t tx_flush_interval, cur_tx_flush_interval;
      uint64_t rebalance_intvl;
@@ -39958,7 +40196,7 @@ index d393aab5e3..1d6b54ff16 100644
  
      tx_flush_interval = smap_get_int(other_config, "tx-flush-interval",
                                       DEFAULT_TX_FLUSH_INTERVAL);
-@@ -4012,7 +4117,7 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
+@@ -4012,7 +4126,7 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
                                false);
  
      rebalance_intvl = smap_get_int(other_config, "pmd-auto-lb-rebal-interval",
@@ -39967,7 +40205,7 @@ index d393aab5e3..1d6b54ff16 100644
  
      /* Input is in min, convert it to msec. */
      rebalance_intvl =
-@@ -4020,9 +4125,38 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
+@@ -4020,9 +4134,38 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
  
      if (pmd_alb->rebalance_intvl != rebalance_intvl) {
          pmd_alb->rebalance_intvl = rebalance_intvl;
@@ -40009,7 +40247,7 @@ index d393aab5e3..1d6b54ff16 100644
      return 0;
  }
  
-@@ -4940,9 +5074,17 @@ reconfigure_datapath(struct dp_netdev *dp)
+@@ -4940,9 +5083,17 @@ reconfigure_datapath(struct dp_netdev *dp)
  
      /* Check for all the ports that need reconfiguration.  We cache this in
       * 'port->need_reconfigure', because netdev_is_reconf_required() can
@@ -40029,7 +40267,7 @@ index d393aab5e3..1d6b54ff16 100644
              port->need_reconfigure = true;
          }
      }
-@@ -5076,7 +5218,7 @@ reconfigure_datapath(struct dp_netdev *dp)
+@@ -5076,7 +5227,7 @@ reconfigure_datapath(struct dp_netdev *dp)
      reload_affected_pmds(dp);
  
      /* Check if PMD Auto LB is to be enabled */
@@ -40038,7 +40276,7 @@ index d393aab5e3..1d6b54ff16 100644
  }
  
  /* Returns true if one of the netdevs in 'dp' requires a reconfiguration */
-@@ -5320,7 +5462,7 @@ pmd_rebalance_dry_run(struct dp_netdev *dp)
+@@ -5320,7 +5471,7 @@ pmd_rebalance_dry_run(struct dp_netdev *dp)
              improvement =
                  ((curr_variance - new_variance) * 100) / curr_variance;
          }
@@ -40047,7 +40285,7 @@ index d393aab5e3..1d6b54ff16 100644
              ret = false;
          }
      }
-@@ -8040,6 +8182,7 @@ dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd,
+@@ -8040,6 +8191,7 @@ dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd,
  
      if (pmd->ctx.now > pmd->rxq_next_cycle_store) {
          uint64_t curr_tsc;
@@ -40055,7 +40293,7 @@ index d393aab5e3..1d6b54ff16 100644
          struct pmd_auto_lb *pmd_alb = &pmd->dp->pmd_alb;
          if (pmd_alb->is_enabled && !pmd->isolated
              && (pmd->perf_stats.counters.n[PMD_CYCLES_ITER_IDLE] >=
-@@ -8056,7 +8199,9 @@ dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd,
+@@ -8056,7 +8208,9 @@ dp_netdev_pmd_try_optimize(struct dp_netdev_pmd_thread *pmd,
                  pmd_load = ((tot_proc * 100) / (tot_idle + tot_proc));
              }
  
@@ -40123,6 +40361,27 @@ index 45bb96b543..353d5cd3ed 100644
          return false;
      }
  
+diff --git a/lib/ipf.c b/lib/ipf.c
+index 446e89d13c..c20bcc0b33 100644
+--- a/lib/ipf.c
++++ b/lib/ipf.c
+@@ -1153,7 +1153,7 @@ ipf_post_execute_reass_pkts(struct ipf *ipf,
+         /* Inner batch loop is constant time since batch size is <=
+          * NETDEV_MAX_BURST. */
+         DP_PACKET_BATCH_REFILL_FOR_EACH (pb_idx, pb_cnt, pkt, pb) {
+-            if (pkt == rp->list->reass_execute_ctx) {
++            if (rp && pkt == rp->list->reass_execute_ctx) {
+                 for (int i = 0; i <= rp->list->last_inuse_idx; i++) {
+                     rp->list->frag_list[i].pkt->md.ct_label = pkt->md.ct_label;
+                     rp->list->frag_list[i].pkt->md.ct_mark = pkt->md.ct_mark;
+@@ -1206,6 +1206,7 @@ ipf_post_execute_reass_pkts(struct ipf *ipf,
+                 ipf_reassembled_list_remove(rp);
+                 dp_packet_delete(rp->pkt);
+                 free(rp);
++                rp = NULL;
+             } else {
+                 dp_packet_batch_refill(pb, pkt, pb_idx);
+             }
 diff --git a/lib/jsonrpc.c b/lib/jsonrpc.c
 index ed748dbde7..e74771e2bc 100644
 --- a/lib/jsonrpc.c
@@ -40553,7 +40812,7 @@ index 90b405c737..309dc59c5f 100644
        </ul>
      </field>
 diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
-index 6187129c00..7051c31053 100644
+index 6187129c00..f080dec61f 100644
 --- a/lib/netdev-dpdk.c
 +++ b/lib/netdev-dpdk.c
 @@ -152,9 +152,18 @@ typedef uint16_t dpdk_port_t;
@@ -40641,7 +40900,51 @@ index 6187129c00..7051c31053 100644
          } else {
              VLOG_WARN("%s: Tx TSO offload is not supported.",
                        netdev_get_name(&dev->up));
-@@ -5110,7 +5134,11 @@ netdev_dpdk_reconfigure(struct netdev *netdev)
+@@ -2691,12 +2715,8 @@ dpdk_pktmbuf_attach_extbuf(struct rte_mbuf *pkt, uint32_t data_len)
+     uint16_t buf_len;
+     void *buf;
+ 
+-    if (rte_pktmbuf_tailroom(pkt) >= sizeof *shinfo) {
+-        shinfo = rte_pktmbuf_mtod(pkt, struct rte_mbuf_ext_shared_info *);
+-    } else {
+-        total_len += sizeof *shinfo + sizeof(uintptr_t);
+-        total_len = RTE_ALIGN_CEIL(total_len, sizeof(uintptr_t));
+-    }
++    total_len += sizeof *shinfo + sizeof(uintptr_t);
++    total_len = RTE_ALIGN_CEIL(total_len, sizeof(uintptr_t));
+ 
+     if (OVS_UNLIKELY(total_len > UINT16_MAX)) {
+         VLOG_ERR("Can't copy packet: too big %u", total_len);
+@@ -2711,20 +2731,14 @@ dpdk_pktmbuf_attach_extbuf(struct rte_mbuf *pkt, uint32_t data_len)
+     }
+ 
+     /* Initialize shinfo. */
+-    if (shinfo) {
+-        shinfo->free_cb = netdev_dpdk_extbuf_free;
+-        shinfo->fcb_opaque = buf;
+-        rte_mbuf_ext_refcnt_set(shinfo, 1);
+-    } else {
+-        shinfo = rte_pktmbuf_ext_shinfo_init_helper(buf, &buf_len,
+-                                                    netdev_dpdk_extbuf_free,
+-                                                    buf);
+-        if (OVS_UNLIKELY(shinfo == NULL)) {
+-            rte_free(buf);
+-            VLOG_ERR("Failed to initialize shared info for mbuf while "
+-                     "attempting to attach an external buffer.");
+-            return NULL;
+-        }
++    shinfo = rte_pktmbuf_ext_shinfo_init_helper(buf, &buf_len,
++                                                netdev_dpdk_extbuf_free,
++                                                buf);
++    if (OVS_UNLIKELY(shinfo == NULL)) {
++        rte_free(buf);
++        VLOG_ERR("Failed to initialize shared info for mbuf while "
++                 "attempting to attach an external buffer.");
++        return NULL;
+     }
+ 
+     rte_pktmbuf_attach_extbuf(pkt, buf, rte_malloc_virt2iova(buf), buf_len,
+@@ -5110,7 +5124,11 @@ netdev_dpdk_reconfigure(struct netdev *netdev)
      if (dev->hw_ol_features & NETDEV_TX_TSO_OFFLOAD) {
          netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_TSO;
          netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_CKSUM;
@@ -40653,7 +40956,7 @@ index 6187129c00..7051c31053 100644
      }
  
      dev->tx_q = netdev_dpdk_alloc_txq(netdev->n_txq);
-@@ -5186,6 +5214,7 @@ netdev_dpdk_vhost_client_reconfigure(struct netdev *netdev)
+@@ -5186,6 +5204,7 @@ netdev_dpdk_vhost_client_reconfigure(struct netdev *netdev)
      struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
      int err;
      uint64_t vhost_flags = 0;
@@ -40661,7 +40964,7 @@ index 6187129c00..7051c31053 100644
      bool zc_enabled;
  
      ovs_mutex_lock(&dev->mutex);
-@@ -5251,17 +5280,24 @@ netdev_dpdk_vhost_client_reconfigure(struct netdev *netdev)
+@@ -5251,17 +5270,24 @@ netdev_dpdk_vhost_client_reconfigure(struct netdev *netdev)
          if (userspace_tso_enabled()) {
              netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_TSO;
              netdev->ol_flags |= NETDEV_TX_OFFLOAD_TCP_CKSUM;
@@ -40696,7 +40999,7 @@ index 6187129c00..7051c31053 100644
  
          err = rte_vhost_driver_start(dev->vhost_id);
 diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
-index c6f3d27409..8d779945a1 100644
+index c6f3d27409..177261f96b 100644
 --- a/lib/netdev-linux.c
 +++ b/lib/netdev-linux.c
 @@ -231,6 +231,14 @@ struct rtnl_link_stats64 {
@@ -40748,6 +41051,42 @@ index c6f3d27409..8d779945a1 100644
          netdev_->ol_flags |= NETDEV_TX_OFFLOAD_IPV4_CKSUM;
      }
  
+@@ -1233,21 +1242,21 @@ netdev_linux_batch_rxq_recv_sock(struct netdev_rxq_linux *rx, int mtu,
+      * aux_buf is allocated so that it can be prepended to TSO buffer. */
+     std_len = virtio_net_hdr_size + VLAN_ETH_HEADER_LEN + mtu;
+     for (i = 0; i < NETDEV_MAX_BURST; i++) {
+-         buffers[i] = dp_packet_new_with_headroom(std_len, DP_NETDEV_HEADROOM);
+-         iovs[i][IOV_PACKET].iov_base = dp_packet_data(buffers[i]);
+-         iovs[i][IOV_PACKET].iov_len = std_len;
+-         if (iovlen == IOV_TSO_SIZE) {
+-             iovs[i][IOV_AUXBUF].iov_base = dp_packet_data(rx->aux_bufs[i]);
+-             iovs[i][IOV_AUXBUF].iov_len = dp_packet_tailroom(rx->aux_bufs[i]);
+-         }
++        buffers[i] = dp_packet_new_with_headroom(std_len, DP_NETDEV_HEADROOM);
++        iovs[i][IOV_PACKET].iov_base = dp_packet_data(buffers[i]);
++        iovs[i][IOV_PACKET].iov_len = std_len;
++        if (iovlen == IOV_TSO_SIZE) {
++            iovs[i][IOV_AUXBUF].iov_base = dp_packet_data(rx->aux_bufs[i]);
++            iovs[i][IOV_AUXBUF].iov_len = dp_packet_tailroom(rx->aux_bufs[i]);
++        }
+ 
+-         mmsgs[i].msg_hdr.msg_name = NULL;
+-         mmsgs[i].msg_hdr.msg_namelen = 0;
+-         mmsgs[i].msg_hdr.msg_iov = iovs[i];
+-         mmsgs[i].msg_hdr.msg_iovlen = iovlen;
+-         mmsgs[i].msg_hdr.msg_control = &cmsg_buffers[i];
+-         mmsgs[i].msg_hdr.msg_controllen = sizeof cmsg_buffers[i];
+-         mmsgs[i].msg_hdr.msg_flags = 0;
++        mmsgs[i].msg_hdr.msg_name = NULL;
++        mmsgs[i].msg_hdr.msg_namelen = 0;
++        mmsgs[i].msg_hdr.msg_iov = iovs[i];
++        mmsgs[i].msg_hdr.msg_iovlen = iovlen;
++        mmsgs[i].msg_hdr.msg_control = &cmsg_buffers[i];
++        mmsgs[i].msg_hdr.msg_controllen = sizeof cmsg_buffers[i];
++        mmsgs[i].msg_hdr.msg_flags = 0;
+     }
+ 
+     do {
 diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c
 index f8c46bbaad..b42d314b65 100644
 --- a/lib/netdev-offload-dpdk.c
@@ -40892,7 +41231,7 @@ index f8c46bbaad..b42d314b65 100644
  
  static int
 diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
-index 550e440b3a..a1d7ffad70 100644
+index 550e440b3a..c00505d181 100644
 --- a/lib/netdev-offload-tc.c
 +++ b/lib/netdev-offload-tc.c
 @@ -198,7 +198,9 @@ del_filter_and_ufid_mapping(struct tcf_id *id, const ovs_u128 *ufid)
@@ -40906,7 +41245,39 @@ index 550e440b3a..a1d7ffad70 100644
      return err;
  }
  
-@@ -1727,7 +1729,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
+@@ -1578,6 +1580,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
+                 flower.key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW;
+             }
+             flower.mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW;
++            mask->ct_state &= ~OVS_CS_F_NEW;
+         }
+ 
+         if (mask->ct_state & OVS_CS_F_ESTABLISHED) {
+@@ -1585,6 +1588,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
+                 flower.key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED;
+             }
+             flower.mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED;
++            mask->ct_state &= ~OVS_CS_F_ESTABLISHED;
+         }
+ 
+         if (mask->ct_state & OVS_CS_F_TRACKED) {
+@@ -1592,14 +1596,13 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
+                 flower.key.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED;
+             }
+             flower.mask.ct_state |= TCA_FLOWER_KEY_CT_FLAGS_TRACKED;
++            mask->ct_state &= ~OVS_CS_F_TRACKED;
+         }
+ 
+         if (flower.key.ct_state & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED) {
+             flower.key.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW);
+             flower.mask.ct_state &= ~(TCA_FLOWER_KEY_CT_FLAGS_NEW);
+         }
+-
+-        mask->ct_state = 0;
+     }
+ 
+     if (mask->ct_zone) {
+@@ -1727,7 +1730,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
      if (get_ufid_tc_mapping(ufid, &id) == 0) {
          VLOG_DBG_RL(&rl, "updating old handle: %d prio: %d",
                      id.handle, id.prio);
@@ -40915,7 +41286,7 @@ index 550e440b3a..a1d7ffad70 100644
      }
  
      prio = get_prio_for_tc_flower(&flower);
-@@ -1907,6 +1909,7 @@ netdev_tc_init_flow_api(struct netdev *netdev)
+@@ -1907,6 +1910,7 @@ netdev_tc_init_flow_api(struct netdev *netdev)
      static struct ovsthread_once block_once = OVSTHREAD_ONCE_INITIALIZER;
      enum tc_qdisc_hook hook = get_tc_qdisc_hook(netdev);
      uint32_t block_id = 0;
@@ -40923,7 +41294,7 @@ index 550e440b3a..a1d7ffad70 100644
      int ifindex;
      int error;
  
-@@ -1917,11 +1920,21 @@ netdev_tc_init_flow_api(struct netdev *netdev)
+@@ -1917,11 +1921,21 @@ netdev_tc_init_flow_api(struct netdev *netdev)
          return -ifindex;
      }
  
@@ -40945,7 +41316,7 @@ index 550e440b3a..a1d7ffad70 100644
          ovsthread_once_done(&block_once);
      }
  
-@@ -1930,7 +1943,6 @@ netdev_tc_init_flow_api(struct netdev *netdev)
+@@ -1930,7 +1944,6 @@ netdev_tc_init_flow_api(struct netdev *netdev)
          ovsthread_once_done(&multi_mask_once);
      }
  
@@ -41097,10 +41468,20 @@ index 42d3335f0f..97320a4dba 100644
      } else {
          a = attrs[OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL];
 diff --git a/lib/odp-util.c b/lib/odp-util.c
-index 746d1e97d4..41cbac0c97 100644
+index 746d1e97d4..b288269fc4 100644
 --- a/lib/odp-util.c
 +++ b/lib/odp-util.c
-@@ -1441,14 +1441,20 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
+@@ -390,7 +390,8 @@ format_odp_push_nsh_action(struct ds *ds,
+         break;
+     }
+     default:
+-        OVS_NOT_REACHED();
++        ds_put_cstr(ds, ",<error: unknown mdtype>");
++        break;
+     }
+     ds_put_format(ds, ")");
+ }
+@@ -1441,14 +1442,20 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
          int n1 = -1;
          if (ovs_scan(&s[n], ",tunnel_out_port=%"SCNi32")%n",
                       &tunnel_out_port, &n1)) {
@@ -41127,7 +41508,7 @@ index 746d1e97d4..41cbac0c97 100644
              goto out;
          }
      }
-@@ -5428,13 +5434,16 @@ erspan_to_attr(struct ofpbuf *a, const void *data_)
+@@ -5428,13 +5435,16 @@ erspan_to_attr(struct ofpbuf *a, const void *data_)
          do {                                               \
              len = 0;
  
@@ -41151,7 +41532,7 @@ index 746d1e97d4..41cbac0c97 100644
      }
  
  #define SCAN_FIELD_NESTED__(NAME, TYPE, SCAN_AS, ATTR, FUNC)  \
-@@ -6225,7 +6234,9 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
+@@ -6225,7 +6235,9 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms,
                      struct ovs_key_nd_extensions *nd_ext_key;
  
                      if (data->igmp_group_ip4 != 0 || data->tcp_flags != 0) {
@@ -41162,7 +41543,7 @@ index 746d1e97d4..41cbac0c97 100644
                                              OVS_KEY_ATTR_ND_EXTENSIONS,
                                              sizeof *nd_ext_key);
                          nd_ext_key->nd_reserved = data->igmp_group_ip4;
-@@ -6275,6 +6286,10 @@ odp_key_from_dp_packet(struct ofpbuf *buf, const struct dp_packet *packet)
+@@ -6275,6 +6287,10 @@ odp_key_from_dp_packet(struct ofpbuf *buf, const struct dp_packet *packet)
  
      nl_msg_put_u32(buf, OVS_KEY_ATTR_PRIORITY, md->skb_priority);
  
@@ -41173,7 +41554,7 @@ index 746d1e97d4..41cbac0c97 100644
      if (flow_tnl_dst_is_set(&md->tunnel)) {
          tun_key_to_attr(buf, &md->tunnel, &md->tunnel, NULL, NULL);
      }
-@@ -7416,15 +7431,18 @@ odp_key_fitness_to_string(enum odp_key_fitness fitness)
+@@ -7416,15 +7432,18 @@ odp_key_fitness_to_string(enum odp_key_fitness fitness)
  
  /* Appends an OVS_ACTION_ATTR_USERSPACE action to 'odp_actions' that specifies
   * Netlink PID 'pid'.  If 'userdata' is nonnull, adds a userdata attribute
@@ -41197,7 +41578,7 @@ index 746d1e97d4..41cbac0c97 100644
  {
      size_t userdata_ofs;
      size_t offset;
-@@ -7432,6 +7450,9 @@ odp_put_userspace_action(uint32_t pid,
+@@ -7432,6 +7451,9 @@ odp_put_userspace_action(uint32_t pid,
      offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_USERSPACE);
      nl_msg_put_u32(odp_actions, OVS_USERSPACE_ATTR_PID, pid);
      if (userdata) {
@@ -41207,7 +41588,7 @@ index 746d1e97d4..41cbac0c97 100644
          userdata_ofs = odp_actions->size + NLA_HDRLEN;
  
          /* The OVS kernel module before OVS 1.11 and the upstream Linux kernel
-@@ -7457,9 +7478,16 @@ odp_put_userspace_action(uint32_t pid,
+@@ -7457,9 +7479,16 @@ odp_put_userspace_action(uint32_t pid,
      if (include_actions) {
          nl_msg_put_flag(odp_actions, OVS_USERSPACE_ATTR_ACTIONS);
      }
@@ -41225,7 +41606,7 @@ index 746d1e97d4..41cbac0c97 100644
  }
  
  void
-@@ -7565,6 +7593,28 @@ struct offsetof_sizeof {
+@@ -7565,6 +7594,28 @@ struct offsetof_sizeof {
      int size;
  };
  
@@ -41254,7 +41635,7 @@ index 746d1e97d4..41cbac0c97 100644
  /* Compares each of the fields in 'key0' and 'key1'.  The fields are specified
   * in 'offsetof_sizeof_arr', which is an array terminated by a 0-size field.
   * Returns true if all of the fields are equal, false if at least one differs.
-@@ -7643,9 +7693,10 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow,
+@@ -7643,9 +7694,10 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow,
                          struct flow_wildcards *wc,
                          bool use_masked)
  {
@@ -41266,7 +41647,7 @@ index 746d1e97d4..41cbac0c97 100644
      if (flow->packet_type != htonl(PT_ETH)) {
          return;
      }
-@@ -7653,11 +7704,13 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow,
+@@ -7653,11 +7705,13 @@ commit_set_ether_action(const struct flow *flow, struct flow *base_flow,
      get_ethernet_key(flow, &key);
      get_ethernet_key(base_flow, &base);
      get_ethernet_key(&wc->masks, &mask);
@@ -41280,7 +41661,7 @@ index 746d1e97d4..41cbac0c97 100644
          put_ethernet_key(&mask, &wc->masks);
      }
  }
-@@ -7781,7 +7834,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
+@@ -7781,7 +7835,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
                         struct ofpbuf *odp_actions, struct flow_wildcards *wc,
                         bool use_masked)
  {
@@ -41289,7 +41670,7 @@ index 746d1e97d4..41cbac0c97 100644
      struct offsetof_sizeof ovs_key_ipv4_offsetof_sizeof_arr[] =
          OVS_KEY_IPV4_OFFSETOF_SIZEOF_ARR;
  
-@@ -7792,6 +7845,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
+@@ -7792,6 +7846,7 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
      get_ipv4_key(flow, &key, false);
      get_ipv4_key(base_flow, &base, false);
      get_ipv4_key(&wc->masks, &mask, true);
@@ -41297,7 +41678,7 @@ index 746d1e97d4..41cbac0c97 100644
      mask.ipv4_proto = 0;        /* Not writeable. */
      mask.ipv4_frag = 0;         /* Not writable. */
  
-@@ -7803,9 +7857,8 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
+@@ -7803,9 +7858,8 @@ commit_set_ipv4_action(const struct flow *flow, struct flow *base_flow,
      if (commit(OVS_KEY_ATTR_IPV4, use_masked, &key, &base, &mask, sizeof key,
                 ovs_key_ipv4_offsetof_sizeof_arr, odp_actions)) {
          put_ipv4_key(&base, base_flow, false);
@@ -41309,7 +41690,7 @@ index 746d1e97d4..41cbac0c97 100644
     }
  }
  
-@@ -7838,7 +7891,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
+@@ -7838,7 +7892,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
                         struct ofpbuf *odp_actions, struct flow_wildcards *wc,
                         bool use_masked)
  {
@@ -41318,7 +41699,7 @@ index 746d1e97d4..41cbac0c97 100644
      struct offsetof_sizeof ovs_key_ipv6_offsetof_sizeof_arr[] =
          OVS_KEY_IPV6_OFFSETOF_SIZEOF_ARR;
  
-@@ -7849,6 +7902,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
+@@ -7849,6 +7903,7 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
      get_ipv6_key(flow, &key, false);
      get_ipv6_key(base_flow, &base, false);
      get_ipv6_key(&wc->masks, &mask, true);
@@ -41326,7 +41707,7 @@ index 746d1e97d4..41cbac0c97 100644
      mask.ipv6_proto = 0;        /* Not writeable. */
      mask.ipv6_frag = 0;         /* Not writable. */
      mask.ipv6_label &= htonl(IPV6_LABEL_MASK); /* Not writable. */
-@@ -7861,9 +7915,8 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
+@@ -7861,9 +7916,8 @@ commit_set_ipv6_action(const struct flow *flow, struct flow *base_flow,
      if (commit(OVS_KEY_ATTR_IPV6, use_masked, &key, &base, &mask, sizeof key,
                 ovs_key_ipv6_offsetof_sizeof_arr, odp_actions)) {
          put_ipv6_key(&base, base_flow, false);
@@ -41338,7 +41719,7 @@ index 746d1e97d4..41cbac0c97 100644
      }
  }
  
-@@ -7894,17 +7947,19 @@ static enum slow_path_reason
+@@ -7894,17 +7948,19 @@ static enum slow_path_reason
  commit_set_arp_action(const struct flow *flow, struct flow *base_flow,
                        struct ofpbuf *odp_actions, struct flow_wildcards *wc)
  {
@@ -41359,7 +41740,7 @@ index 746d1e97d4..41cbac0c97 100644
          put_arp_key(&mask, &wc->masks);
          return SLOW_ACTION;
      }
-@@ -7931,7 +7986,7 @@ static enum slow_path_reason
+@@ -7931,7 +7987,7 @@ static enum slow_path_reason
  commit_set_icmp_action(const struct flow *flow, struct flow *base_flow,
                         struct ofpbuf *odp_actions, struct flow_wildcards *wc)
  {
@@ -41368,7 +41749,7 @@ index 746d1e97d4..41cbac0c97 100644
      struct offsetof_sizeof ovs_key_icmp_offsetof_sizeof_arr[] =
          OVS_KEY_ICMP_OFFSETOF_SIZEOF_ARR;
      enum ovs_key_attr attr;
-@@ -7947,10 +8002,12 @@ commit_set_icmp_action(const struct flow *flow, struct flow *base_flow,
+@@ -7947,10 +8003,12 @@ commit_set_icmp_action(const struct flow *flow, struct flow *base_flow,
      get_icmp_key(flow, &key);
      get_icmp_key(base_flow, &base);
      get_icmp_key(&wc->masks, &mask);
@@ -41381,7 +41762,7 @@ index 746d1e97d4..41cbac0c97 100644
          put_icmp_key(&mask, &wc->masks);
          return SLOW_ACTION;
      }
-@@ -7998,17 +8055,19 @@ commit_set_nd_action(const struct flow *flow, struct flow *base_flow,
+@@ -7998,17 +8056,19 @@ commit_set_nd_action(const struct flow *flow, struct flow *base_flow,
                       struct ofpbuf *odp_actions,
                       struct flow_wildcards *wc, bool use_masked)
  {
@@ -41402,7 +41783,7 @@ index 746d1e97d4..41cbac0c97 100644
          put_nd_key(&mask, &wc->masks);
          return SLOW_ACTION;
      }
-@@ -8022,18 +8081,20 @@ commit_set_nd_extensions_action(const struct flow *flow,
+@@ -8022,18 +8082,20 @@ commit_set_nd_extensions_action(const struct flow *flow,
                                  struct ofpbuf *odp_actions,
                                  struct flow_wildcards *wc, bool use_masked)
  {
@@ -41424,7 +41805,7 @@ index 746d1e97d4..41cbac0c97 100644
          put_nd_extensions_key(&mask, &wc->masks);
          return SLOW_ACTION;
      }
-@@ -8248,7 +8309,7 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow,
+@@ -8248,7 +8310,7 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow,
                         bool use_masked)
  {
      enum ovs_key_attr key_type;
@@ -41433,7 +41814,7 @@ index 746d1e97d4..41cbac0c97 100644
      struct offsetof_sizeof ovs_key_tp_offsetof_sizeof_arr[] =
          OVS_KEY_TCP_OFFSETOF_SIZEOF_ARR;
  
-@@ -8274,10 +8335,12 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow,
+@@ -8274,10 +8336,12 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow,
      get_tp_key(flow, &key);
      get_tp_key(base_flow, &base);
      get_tp_key(&wc->masks, &mask);
@@ -41446,7 +41827,7 @@ index 746d1e97d4..41cbac0c97 100644
          put_tp_key(&mask, &wc->masks);
      }
  }
-@@ -8301,7 +8364,7 @@ commit_set_priority_action(const struct flow *flow, struct flow *base_flow,
+@@ -8301,7 +8365,7 @@ commit_set_priority_action(const struct flow *flow, struct flow *base_flow,
      if (commit(OVS_KEY_ATTR_PRIORITY, use_masked, &key, &base, &mask,
                 sizeof key, ovs_key_prio_offsetof_sizeof_arr, odp_actions)) {
          base_flow->skb_priority = base;
@@ -41455,7 +41836,7 @@ index 746d1e97d4..41cbac0c97 100644
      }
  }
  
-@@ -8325,7 +8388,7 @@ commit_set_pkt_mark_action(const struct flow *flow, struct flow *base_flow,
+@@ -8325,7 +8389,7 @@ commit_set_pkt_mark_action(const struct flow *flow, struct flow *base_flow,
                 sizeof key, ovs_key_pkt_mark_offsetof_sizeof_arr,
                 odp_actions)) {
          base_flow->pkt_mark = base;
@@ -41487,10 +41868,26 @@ index 4ecce1aac5..936fadf175 100644
                             struct ofpbuf *odp_actions,
                             const char *tnl_type);
 diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
-index ddef3b0c87..ef8b2b4527 100644
+index ddef3b0c87..6a6fdb3e5f 100644
 --- a/lib/ofp-actions.c
 +++ b/lib/ofp-actions.c
-@@ -6657,6 +6657,7 @@ parse_CT(char *arg, const struct ofpact_parse_params *pp)
+@@ -4346,6 +4346,7 @@ decode_NXAST_RAW_ENCAP(const struct nx_action_encap *nae,
+ {
+     struct ofpact_encap *encap;
+     const struct ofp_ed_prop_header *ofp_prop;
++    const size_t encap_ofs = out->size;
+     size_t props_len;
+     uint16_t n_props = 0;
+     int err;
+@@ -4373,6 +4374,7 @@ decode_NXAST_RAW_ENCAP(const struct nx_action_encap *nae,
+         }
+         n_props++;
+     }
++    encap = ofpbuf_at_assert(out, encap_ofs, sizeof *encap);
+     encap->n_props = n_props;
+     out->header = &encap->ofpact;
+     ofpact_finish_ENCAP(out, &encap);
+@@ -6657,6 +6659,7 @@ parse_CT(char *arg, const struct ofpact_parse_params *pp)
      }
  
      if (ofpbuf_oversized(pp->ofpacts)) {
@@ -42297,9 +42694,18 @@ index eda265dfc5..a635ff7689 100644
  #define SHA1_FMT \
          "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" \
 diff --git a/lib/tc.c b/lib/tc.c
-index 12af0192b6..e772aa515c 100644
+index 12af0192b6..5a6f76a209 100644
 --- a/lib/tc.c
 +++ b/lib/tc.c
+@@ -456,7 +456,7 @@ nl_parse_flower_mpls(struct nlattr **attrs, struct tc_flower *flower)
+     if (attrs[TCA_FLOWER_KEY_MPLS_BOS]) {
+         bos = nl_attr_get_u8(attrs[TCA_FLOWER_KEY_MPLS_BOS]);
+         set_mpls_lse_bos(&flower->key.mpls_lse, bos);
+-        set_mpls_lse_ttl(&flower->mask.mpls_lse, 0xff);
++        set_mpls_lse_bos(&flower->mask.mpls_lse, 0xff);
+     }
+ 
+     if (attrs[TCA_FLOWER_KEY_MPLS_TC]) {
 @@ -934,6 +934,7 @@ nl_parse_act_pedit(struct nlattr *options, struct tc_flower *flower)
              int flower_off = m->flower_offset;
              int sz = m->size;
@@ -42384,7 +42790,7 @@ index 7ad8758fe6..067dcad157 100644
                    void *dst, unsigned int dst_len, unsigned int dst_ofs,
                    unsigned int n_bits);
 diff --git a/ofproto/connmgr.c b/ofproto/connmgr.c
-index 51d656cba9..aee676d93e 100644
+index 51d656cba9..fd926cbb82 100644
 --- a/ofproto/connmgr.c
 +++ b/ofproto/connmgr.c
 @@ -190,8 +190,8 @@ struct ofservice {
@@ -42445,6 +42851,26 @@ index 51d656cba9..aee676d93e 100644
  }
  
  /* Finds and returns the ofservice within 'mgr' that has the given
+@@ -2131,7 +2140,7 @@ ofmonitor_report(struct connmgr *mgr, struct rule *rule,
+                  const struct rule_actions *old_actions)
+     OVS_REQUIRES(ofproto_mutex)
+ {
+-    if (rule_is_hidden(rule)) {
++    if (!mgr || rule_is_hidden(rule)) {
+         return;
+     }
+ 
+@@ -2235,6 +2244,10 @@ ofmonitor_flush(struct connmgr *mgr)
+ {
+     struct ofconn *ofconn;
+ 
++    if (!mgr) {
++        return;
++    }
++
+     LIST_FOR_EACH (ofconn, connmgr_node, &mgr->conns) {
+         struct rconn_packet_counter *counter = ofconn->monitor_counter;
+ 
 diff --git a/ofproto/ipfix-gen-entities b/ofproto/ipfix-gen-entities
 index 0be719967d..d5abe9c2ed 100755
 --- a/ofproto/ipfix-gen-entities
@@ -42638,10 +43064,10 @@ index 08830d8371..8594afad4a 100644
      ovs_mutex_unlock(&ofproto_mutex);
  }
 diff --git a/ovsdb/automake.mk b/ovsdb/automake.mk
-index b895f42925..d60f3f4ec8 100644
+index b895f42925..446d6c1362 100644
 --- a/ovsdb/automake.mk
 +++ b/ovsdb/automake.mk
-@@ -106,7 +106,7 @@ CLEANFILES += $(OVSIDL_BUILT)
+@@ -106,11 +106,12 @@ CLEANFILES += $(OVSIDL_BUILT)
  # However, current versions of Automake seem to output all variable
  # assignments before any targets, so it doesn't seem to be a problem,
  # at least for now.
@@ -42650,6 +43076,11 @@ index b895f42925..d60f3f4ec8 100644
  
  # ovsdb-doc
  EXTRA_DIST += ovsdb/ovsdb-doc
+ OVSDB_DOC = $(run_python) $(srcdir)/ovsdb/ovsdb-doc
++ovsdb/ovsdb-doc: python/ovs/dirs.py
+ 
+ # ovsdb-dot
+ EXTRA_DIST += ovsdb/ovsdb-dot.in ovsdb/dot2pic
 diff --git a/ovsdb/dot2pic b/ovsdb/dot2pic
 index de67261ac6..2f858e19d5 100755
 --- a/ovsdb/dot2pic
@@ -42698,6 +43129,28 @@ index c82a79c9ff..f35faadfe0 100644
      }
      if (fd < 0) {
          const char *op = (open_mode == OVSDB_LOG_CREATE_EXCL ? "create"
+diff --git a/ovsdb/ovsdb-client.c b/ovsdb/ovsdb-client.c
+index 72756eb1f2..ba28e36d78 100644
+--- a/ovsdb/ovsdb-client.c
++++ b/ovsdb/ovsdb-client.c
+@@ -1664,14 +1664,15 @@ static void
+ do_needs_conversion(struct jsonrpc *rpc, const char *database_ OVS_UNUSED,
+                     int argc OVS_UNUSED, char *argv[])
+ {
++    const char *schema_file_name = argv[argc - 1];
+     struct ovsdb_schema *schema1;
+-    check_ovsdb_error(ovsdb_schema_from_file(argv[0], &schema1));
++    check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema1));
+ 
+     char *database = schema1->name;
+     open_rpc(1, NEED_DATABASE, argc, argv, &rpc, &database);
+ 
+     if (is_database_clustered(rpc, database)) {
+-        ovsdb_schema_persist_ephemeral_columns(schema1, argv[0]);
++        ovsdb_schema_persist_ephemeral_columns(schema1, schema_file_name);
+     }
+ 
+     struct ovsdb_schema *schema2 = fetch_schema(rpc, schema1->name);
 diff --git a/ovsdb/ovsdb-doc b/ovsdb/ovsdb-doc
 index 406c293114..10d0c0c134 100755
 --- a/ovsdb/ovsdb-doc
@@ -43044,7 +43497,7 @@ index 18c83fe9c2..dd14d81091 100644
      struct hmap servers;
      struct ovsdb_error *error =
 diff --git a/ovsdb/raft.c b/ovsdb/raft.c
-index 4789bc4f22..ff06add0bf 100644
+index 4789bc4f22..d08a7bcb62 100644
 --- a/ovsdb/raft.c
 +++ b/ovsdb/raft.c
 @@ -36,6 +36,7 @@
@@ -43093,17 +43546,52 @@ index 4789bc4f22..ff06add0bf 100644
      return raft;
  }
  
-@@ -932,6 +948,9 @@ raft_add_conn(struct raft *raft, struct jsonrpc_session *js,
+@@ -918,6 +934,34 @@ raft_reset_ping_timer(struct raft *raft)
+     raft->ping_timeout = time_msec() + raft->election_timer / 3;
+ }
+ 
++static void
++raft_conn_update_probe_interval(struct raft *raft, struct raft_conn *r_conn)
++{
++    /* Inactivity probe will be sent if connection will remain idle for the
++     * time of an election timeout.  Connection will be dropped if inactivity
++     * will last twice that time.
++     *
++     * It's not enough to just have heartbeats if connection is still
++     * established, but no packets received from the other side.  Without
++     * inactivity probe follower will just try to initiate election
++     * indefinitely staying in 'candidate' role.  And the leader will continue
++     * to send heartbeats to the dead connection thinking that remote server
++     * is still part of the cluster. */
++    int probe_interval = raft->election_timer + ELECTION_RANGE_MSEC;
++
++    jsonrpc_session_set_probe_interval(r_conn->js, probe_interval);
++}
++
++static void
++raft_update_probe_intervals(struct raft *raft)
++{
++    struct raft_conn *r_conn;
++
++    LIST_FOR_EACH (r_conn, list_node, &raft->conns) {
++        raft_conn_update_probe_interval(raft, r_conn);
++    }
++}
++
+ static void
+ raft_add_conn(struct raft *raft, struct jsonrpc_session *js,
+               const struct uuid *sid, bool incoming)
+@@ -932,6 +976,9 @@ raft_add_conn(struct raft *raft, struct jsonrpc_session *js,
                                                &conn->sid);
      conn->incoming = incoming;
      conn->js_seqno = jsonrpc_session_get_seqno(conn->js);
-+    jsonrpc_session_set_probe_interval(js, 0);
++    raft_conn_update_probe_interval(raft, conn);
 +    jsonrpc_session_set_backlog_threshold(js, raft->conn_backlog_max_n_msgs,
 +                                              raft->conn_backlog_max_n_bytes);
  }
  
  /* Starts the local server in an existing Raft cluster, using the local copy of
-@@ -1007,6 +1026,23 @@ raft_get_sid(const struct raft *raft)
+@@ -1007,6 +1054,23 @@ raft_get_sid(const struct raft *raft)
      return &raft->sid;
  }
  
@@ -43127,7 +43615,7 @@ index 4789bc4f22..ff06add0bf 100644
  /* Returns true if 'raft' has completed joining its cluster, has not left or
   * initiated leaving the cluster, does not have failed disk storage, and is
   * apparently connected to the leader in a healthy way (or is itself the
-@@ -1020,12 +1056,22 @@ raft_get_sid(const struct raft *raft)
+@@ -1020,12 +1084,22 @@ raft_get_sid(const struct raft *raft)
  bool
  raft_is_connected(const struct raft *raft)
  {
@@ -43152,7 +43640,7 @@ index 4789bc4f22..ff06add0bf 100644
      return ret;
  }
  
-@@ -1397,8 +1443,19 @@ raft_conn_run(struct raft *raft, struct raft_conn *conn)
+@@ -1397,8 +1471,19 @@ raft_conn_run(struct raft *raft, struct raft_conn *conn)
      jsonrpc_session_run(conn->js);
  
      unsigned int new_seqno = jsonrpc_session_get_seqno(conn->js);
@@ -43173,7 +43661,7 @@ index 4789bc4f22..ff06add0bf 100644
      conn->js_seqno = new_seqno;
      if (just_connected) {
          if (raft->joining) {
-@@ -1641,6 +1698,7 @@ raft_start_election(struct raft *raft, bool leadership_transfer)
+@@ -1641,6 +1726,7 @@ raft_start_election(struct raft *raft, bool leadership_transfer)
      }
  
      ovs_assert(raft->role != RAFT_LEADER);
@@ -43181,7 +43669,7 @@ index 4789bc4f22..ff06add0bf 100644
      raft->role = RAFT_CANDIDATE;
      /* If there was no leader elected since last election, we know we are
       * retrying now. */
-@@ -1684,7 +1742,9 @@ raft_start_election(struct raft *raft, bool leadership_transfer)
+@@ -1684,7 +1770,9 @@ raft_start_election(struct raft *raft, bool leadership_transfer)
                  .leadership_transfer = leadership_transfer,
              },
          };
@@ -43192,7 +43680,7 @@ index 4789bc4f22..ff06add0bf 100644
      }
  
      /* Vote for ourselves. */
-@@ -2513,13 +2573,14 @@ raft_server_init_leader(struct raft *raft, struct raft_server *s)
+@@ -2513,13 +2601,14 @@ raft_server_init_leader(struct raft *raft, struct raft_server *s)
      s->match_index = 0;
      s->phase = RAFT_PHASE_STABLE;
      s->replied = false;
@@ -43208,7 +43696,23 @@ index 4789bc4f22..ff06add0bf 100644
      raft->candidate_retrying = false;
  }
  
-@@ -2960,6 +3021,15 @@ raft_update_leader(struct raft *raft, const struct uuid *sid)
+@@ -2731,6 +2820,7 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index)
+                           raft->election_timer, e->election_timer);
+                 raft->election_timer = e->election_timer;
+                 raft->election_timer_new = 0;
++                raft_update_probe_intervals(raft);
+             }
+             if (e->servers) {
+                 /* raft_run_reconfigure() can write a new Raft entry, which can
+@@ -2747,6 +2837,7 @@ raft_update_commit_index(struct raft *raft, uint64_t new_commit_index)
+                 VLOG_INFO("Election timer changed from %"PRIu64" to %"PRIu64,
+                           raft->election_timer, e->election_timer);
+                 raft->election_timer = e->election_timer;
++                raft_update_probe_intervals(raft);
+             }
+         }
+         /* Check if any pending command can be completed, and complete it.
+@@ -2960,6 +3051,15 @@ raft_update_leader(struct raft *raft, const struct uuid *sid)
          };
          ignore(ovsdb_log_write_and_free(raft->log, raft_record_to_json(&r)));
      }
@@ -43224,7 +43728,7 @@ index 4789bc4f22..ff06add0bf 100644
      return true;
  }
  
-@@ -3260,7 +3330,20 @@ raft_send_install_snapshot_request(struct raft *raft,
+@@ -3260,7 +3360,20 @@ raft_send_install_snapshot_request(struct raft *raft,
              .election_timer = raft->election_timer, /* use latest value */
          }
      };
@@ -43246,7 +43750,7 @@ index 4789bc4f22..ff06add0bf 100644
  }
  
  static void
-@@ -3913,7 +3996,7 @@ raft_handle_install_snapshot_request__(
+@@ -3913,7 +4026,7 @@ raft_handle_install_snapshot_request__(
      struct ovsdb_error *error = raft_save_snapshot(raft, new_log_start,
                                                     &new_snapshot);
      if (error) {
@@ -43255,7 +43759,7 @@ index 4789bc4f22..ff06add0bf 100644
          VLOG_WARN("could not save snapshot: %s", error_s);
          free(error_s);
          return false;
-@@ -3977,6 +4060,8 @@ raft_handle_install_snapshot_reply(
+@@ -3977,6 +4090,8 @@ raft_handle_install_snapshot_reply(
          }
      }
  
@@ -43264,7 +43768,7 @@ index 4789bc4f22..ff06add0bf 100644
      if (rpy->last_index != raft->log_start - 1 ||
          rpy->last_term != raft->snap.term) {
          static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
-@@ -3992,8 +4077,9 @@ raft_handle_install_snapshot_reply(
+@@ -3992,8 +4107,9 @@ raft_handle_install_snapshot_reply(
      VLOG_INFO_RL(&rl, "cluster "CID_FMT": installed snapshot on server %s "
                   " up to %"PRIu64":%"PRIu64, CID_ARGS(&raft->cid),
                   s->nickname, rpy->last_term, rpy->last_index);
@@ -43276,7 +43780,7 @@ index 4789bc4f22..ff06add0bf 100644
  }
  
  /* Returns true if 'raft' has grown enough since the last snapshot that
-@@ -4143,9 +4229,7 @@ raft_handle_execute_command_request__(
+@@ -4143,9 +4259,7 @@ raft_handle_execute_command_request__(
      cmd->sid = rq->common.sid;
  
      enum raft_command_status status = cmd->status;
@@ -43287,7 +43791,16 @@ index 4789bc4f22..ff06add0bf 100644
      return status;
  }
  
-@@ -4639,6 +4723,42 @@ raft_unixctl_change_election_timer(struct unixctl_conn *conn,
+@@ -4366,6 +4480,8 @@ raft_unixctl_status(struct unixctl_conn *conn,
+                   : raft->leaving ? "leaving cluster"
+                   : raft->left ? "left cluster"
+                   : raft->failed ? "failed"
++                  : raft->candidate_retrying
++                      ? "disconnected from the cluster (election timeout)"
+                   : "cluster member");
+     if (raft->joining) {
+         ds_put_format(&s, "Remotes for joining:");
+@@ -4639,6 +4755,42 @@ raft_unixctl_change_election_timer(struct unixctl_conn *conn,
      unixctl_command_reply(conn, "change of election timer initiated.");
  }
  
@@ -43330,7 +43843,7 @@ index 4789bc4f22..ff06add0bf 100644
  static void
  raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED,
                            int argc OVS_UNUSED, const char *argv[],
-@@ -4667,6 +4787,8 @@ raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED,
+@@ -4667,6 +4819,8 @@ raft_unixctl_failure_test(struct unixctl_conn *conn OVS_UNUSED,
                  raft_reset_election_timer(raft);
              }
          }
@@ -43339,7 +43852,7 @@ index 4789bc4f22..ff06add0bf 100644
      } else if (!strcmp(test, "clear")) {
          failure_test = FT_NO_TEST;
          unixctl_command_reply(conn, "test dismissed");
-@@ -4697,6 +4819,9 @@ raft_init(void)
+@@ -4697,6 +4851,9 @@ raft_init(void)
                               raft_unixctl_kick, NULL);
      unixctl_command_register("cluster/change-election-timer", "DB TIME", 2, 2,
                               raft_unixctl_change_election_timer, NULL);
@@ -43534,10 +44047,128 @@ index 9852786466..8bbcd824f4 100644
  version.py
 +dirs.py
 diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py
-index 020291d486..5850ac7abf 100644
+index 020291d486..4226d1cb2f 100644
 --- a/python/ovs/db/idl.py
 +++ b/python/ovs/db/idl.py
-@@ -1567,10 +1567,9 @@ class Transaction(object):
+@@ -12,6 +12,7 @@
+ # See the License for the specific language governing permissions and
+ # limitations under the License.
+ 
++import collections
+ import functools
+ import uuid
+ 
+@@ -39,6 +40,10 @@ OVSDB_UPDATE2 = 1
+ CLUSTERED = "clustered"
+ 
+ 
++Notice = collections.namedtuple('Notice', ('event', 'row', 'updates'))
++Notice.__new__.__defaults__ = (None,)  # default updates=None
++
++
+ class Idl(object):
+     """Open vSwitch Database Interface Definition Language (OVSDB IDL).
+ 
+@@ -614,6 +619,7 @@ class Idl(object):
+             raise error.Error("<table-updates> is not an object",
+                               table_updates)
+ 
++        notices = []
+         for table_name, table_update in table_updates.items():
+             table = tables.get(table_name)
+             if not table:
+@@ -639,7 +645,9 @@ class Idl(object):
+                                       % (table_name, uuid_string))
+ 
+                 if version == OVSDB_UPDATE2:
+-                    if self.__process_update2(table, uuid, row_update):
++                    changes = self.__process_update2(table, uuid, row_update)
++                    if changes:
++                        notices.append(changes)
+                         self.change_seqno += 1
+                     continue
+ 
+@@ -652,17 +660,20 @@ class Idl(object):
+                     raise error.Error('<row-update> missing "old" and '
+                                       '"new" members', row_update)
+ 
+-                if self.__process_update(table, uuid, old, new):
++                changes = self.__process_update(table, uuid, old, new)
++                if changes:
++                    notices.append(changes)
+                     self.change_seqno += 1
++        for notice in notices:
++            self.notify(*notice)
+ 
+     def __process_update2(self, table, uuid, row_update):
++        """Returns Notice if a column changed, False otherwise."""
+         row = table.rows.get(uuid)
+-        changed = False
+         if "delete" in row_update:
+             if row:
+                 del table.rows[uuid]
+-                self.notify(ROW_DELETE, row)
+-                changed = True
++                return Notice(ROW_DELETE, row)
+             else:
+                 # XXX rate-limit
+                 vlog.warn("cannot delete missing row %s from table"
+@@ -681,29 +692,27 @@ class Idl(object):
+             changed = self.__row_update(table, row, row_update)
+             table.rows[uuid] = row
+             if changed:
+-                self.notify(ROW_CREATE, row)
++                return Notice(ROW_CREATE, row)
+         elif "modify" in row_update:
+             if not row:
+                 raise error.Error('Modify non-existing row')
+ 
+             old_row = self.__apply_diff(table, row, row_update['modify'])
+-            self.notify(ROW_UPDATE, row, Row(self, table, uuid, old_row))
+-            changed = True
++            return Notice(ROW_UPDATE, row, Row(self, table, uuid, old_row))
+         else:
+             raise error.Error('<row-update> unknown operation',
+                               row_update)
+-        return changed
++        return False
+ 
+     def __process_update(self, table, uuid, old, new):
+-        """Returns True if a column changed, False otherwise."""
++        """Returns Notice if a column changed, False otherwise."""
+         row = table.rows.get(uuid)
+         changed = False
+         if not new:
+             # Delete row.
+             if row:
+                 del table.rows[uuid]
+-                changed = True
+-                self.notify(ROW_DELETE, row)
++                return Notice(ROW_DELETE, row)
+             else:
+                 # XXX rate-limit
+                 vlog.warn("cannot delete missing row %s from table %s"
+@@ -723,7 +732,7 @@ class Idl(object):
+             if op == ROW_CREATE:
+                 table.rows[uuid] = row
+             if changed:
+-                self.notify(ROW_CREATE, row)
++                return Notice(ROW_CREATE, row)
+         else:
+             op = ROW_UPDATE
+             if not row:
+@@ -737,8 +746,8 @@ class Idl(object):
+             if op == ROW_CREATE:
+                 table.rows[uuid] = row
+             if changed:
+-                self.notify(op, row, Row.from_json(self, table, uuid, old))
+-        return changed
++                return Notice(op, row, Row.from_json(self, table, uuid, old))
++        return False
+ 
+     def __check_server_db(self):
+         """Returns True if this is a valid server database, False otherwise."""
+@@ -1567,10 +1576,9 @@ class Transaction(object):
                      for col, val in row._mutations['_inserts'].items():
                          column = row._table.columns[col]
                          if column.type.is_map():
@@ -43709,6 +44340,19 @@ index c94f2f5358..15eec6d4c0 100644
      # For RHEL 7.2, 7.4, 7.6, 7.7, and 7.8
      if [ -x "%{_datadir}/openvswitch/scripts/ovs-kmod-manage.sh" ]; then
          %{_datadir}/openvswitch/scripts/ovs-kmod-manage.sh
+diff --git a/rhel/openvswitch.spec.in b/rhel/openvswitch.spec.in
+index b0383ed75e..ee8b3c9eac 100644
+--- a/rhel/openvswitch.spec.in
++++ b/rhel/openvswitch.spec.in
+@@ -39,7 +39,7 @@ BuildRequires: checkpolicy, selinux-policy-devel
+ BuildRequires: autoconf, automake, libtool
+ BuildRequires: python3-sphinx
+ BuildRequires: unbound-devel
+-BuildRequires: unwind-devel
++BuildRequires: libunwind-devel
+ 
+ %bcond_without check
+ %bcond_with check_datapath_kernel
 diff --git a/rhel/usr_lib_systemd_system_ovsdb-server.service b/rhel/usr_lib_systemd_system_ovsdb-server.service
 index 4c170c09b4..98338b9dfb 100644
 --- a/rhel/usr_lib_systemd_system_ovsdb-server.service
@@ -43779,10 +44423,20 @@ index 2adaf231fe..beb0ab0d66 100644
  allow openvswitch_load_module_t modules_object_t:dir { getattr open read search };
  allow openvswitch_load_module_t openvswitch_load_module_exec_t:file { entrypoint };
 diff --git a/tests/automake.mk b/tests/automake.mk
-index 9c7ebdce9b..3d90f97687 100644
+index 9c7ebdce9b..d51d175f40 100644
 --- a/tests/automake.mk
 +++ b/tests/automake.mk
-@@ -152,7 +152,8 @@ SYSTEM_KMOD_TESTSUITE_AT = \
+@@ -132,7 +132,8 @@ FUZZ_REGRESSION_TESTS = \
+ 	tests/fuzz-regression/ofp_print_fuzzer-5722747668791296 \
+ 	tests/fuzz-regression/ofp_print_fuzzer-6285128790704128 \
+ 	tests/fuzz-regression/ofp_print_fuzzer-6470117922701312 \
+-	tests/fuzz-regression/ofp_print_fuzzer-6502620041576448
++	tests/fuzz-regression/ofp_print_fuzzer-6502620041576448 \
++	tests/fuzz-regression/ofp_print_fuzzer-6540965472632832
+ $(srcdir)/tests/fuzz-regression-list.at: tests/automake.mk
+ 	$(AM_V_GEN)for name in $(FUZZ_REGRESSION_TESTS); do \
+             basename=`echo $$name | sed 's,^.*/,,'`; \
+@@ -152,7 +153,8 @@ SYSTEM_KMOD_TESTSUITE_AT = \
  SYSTEM_USERSPACE_TESTSUITE_AT = \
  	tests/system-userspace-testsuite.at \
  	tests/system-userspace-macros.at \
@@ -43861,8 +44515,26 @@ index 88818618be..cdcd72c156 100644
 +])
 +OVS_VSWITCHD_STOP
 +AT_CLEANUP
+diff --git a/tests/daemon.at b/tests/daemon.at
+index a7982de381..39d9aa391e 100644
+--- a/tests/daemon.at
++++ b/tests/daemon.at
+@@ -218,11 +218,11 @@ OVS_WAIT_UNTIL([test -s ovsdb-server.pid])
+ OVS_WAIT_UNTIL([sc query ovsdb-server | grep STATE | grep RUNNING > /dev/null 2>&1])
+ AT_CHECK([kill -0 `cat ovsdb-server.pid`], [0], [ignore])
+ AT_CHECK([ovs-appctl -t ovsdb-server ovsdb-server/list-dbs], [0],
+-[Open_vSwitch
++[_Server
+ ])
+ AT_CHECK([sc stop ovsdb-server], [0], [ignore])
+ OVS_WAIT_UNTIL([test ! -s ovsdb-server.pid])
+-AT_CHECK([sc query ovsdb-server | grep STATE | grep STOPPED], [0], [ignore])
++OVS_WAIT_UNTIL([sc query ovsdb-server | grep STATE | grep STOPPED > /dev/null 2>&1])
+ AT_CHECK([sc delete ovsdb-server], [0], [[[SC]] DeleteService SUCCESS
+ ])
+ AT_CLEANUP
 diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
-index 0aeb4e788f..1651e02d29 100644
+index 0aeb4e788f..82a23d0cae 100644
 --- a/tests/dpif-netdev.at
 +++ b/tests/dpif-netdev.at
 @@ -371,7 +371,7 @@ m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD],
@@ -43937,6 +44609,39 @@ index 0aeb4e788f..1651e02d29 100644
  ])
  
     # Check that ip address and udp port were correctly modified in output packets.
+@@ -506,3 +506,20 @@ udp,in_port=ANY,dl_vlan=99,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=00:06:07:08:09:
+ 
+ DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS([dummy])
+ DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS([dummy-pmd])
++
++AT_SETUP([dpif-netdev - check dpctl/add-flow in_port exact match])
++OVS_VSWITCHD_START(
++  [add-port br0 p1 \
++   -- set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p0.sock \
++   -- set bridge br0 datapath-type=dummy \
++                     other-config:datapath-id=1234 fail-mode=secure])
++
++AT_CHECK([ovs-appctl dpctl/add-flow "eth(),eth_type(0x0800),ipv4()" "3"], [2],
++[], [dnl
++ovs-vswitchd: updating flow table (Invalid argument)
++ovs-appctl: ovs-vswitchd: server returned an error
++])
++OVS_WAIT_UNTIL([grep "flow: in_port is not an exact match" ovs-vswitchd.log])
++OVS_VSWITCHD_STOP(["/flow: in_port is not an exact match/d
++/failed to put/d"])
++AT_CLEANUP
+diff --git a/tests/fuzz-regression-list.at b/tests/fuzz-regression-list.at
+index e3173fb88f..2347c690ef 100644
+--- a/tests/fuzz-regression-list.at
++++ b/tests/fuzz-regression-list.at
+@@ -21,3 +21,4 @@ TEST_FUZZ_REGRESSION([ofp_print_fuzzer-5722747668791296])
+ TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6285128790704128])
+ TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6470117922701312])
+ TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6502620041576448])
++TEST_FUZZ_REGRESSION([ofp_print_fuzzer-6540965472632832])
+diff --git a/tests/fuzz-regression/ofp_print_fuzzer-6540965472632832 b/tests/fuzz-regression/ofp_print_fuzzer-6540965472632832
+new file mode 100644
+index 0000000000..e69de29bb2
 diff --git a/tests/idltest.ovsschema b/tests/idltest.ovsschema
 index bee79fc50f..3ddb612b0c 100644
 --- a/tests/idltest.ovsschema
@@ -44259,6 +44964,41 @@ index 55c7a6e179..c8babe3612 100644
  AT_CHECK([RUN_OVS_VSCTL([-- --id=@m create Datapath datapath_version=0 'capabilities={recirc=true}' -- set Open_vSwitch . datapaths:"system"=@m])], [0], [stdout])
  AT_CHECK([RUN_OVS_VSCTL([list-dp-cap system])], [0], [recirc=true
  ])
+diff --git a/tests/ovsdb-client.at b/tests/ovsdb-client.at
+index 8d777a0275..5e3b26aea8 100644
+--- a/tests/ovsdb-client.at
++++ b/tests/ovsdb-client.at
+@@ -12,6 +12,30 @@ AT_CHECK([ovsdb-client get-schema-cksum unix:socket ordinals], [0], [12345678 9
+ OVSDB_SERVER_SHUTDOWN
+ AT_CLEANUP
+ 
++AT_SETUP([ovsdb-client needs-conversion (no conversion needed)])
++AT_KEYWORDS([ovsdb client file positive])
++ordinal_schema > schema
++touch .db.~lock~
++AT_CHECK([ovsdb-tool create db schema], [0], [], [ignore])
++AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db], [0], [ignore], [ignore])
++AT_CHECK([ovsdb-client needs-conversion unix:socket schema], [0], [no
++])
++OVSDB_SERVER_SHUTDOWN
++AT_CLEANUP
++
++AT_SETUP([ovsdb-client needs-conversion (conversion needed)])
++AT_KEYWORDS([ovsdb client file positive])
++ordinal_schema > schema
++touch .db.~lock~
++AT_CHECK([ovsdb-tool create db schema], [0], [], [ignore])
++AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --remote=punix:socket db], [0], [ignore], [ignore])
++sed 's/5\.1\.3/5.1.4/' < schema > schema2
++AT_CHECK([diff schema schema2], [1], [ignore])
++AT_CHECK([ovsdb-client needs-conversion unix:socket schema2], [0], [yes
++])
++OVSDB_SERVER_SHUTDOWN
++AT_CLEANUP
++
+ AT_SETUP([ovsdb-client backup and restore])
+ AT_KEYWORDS([ovsdb client positive])
+ 
 diff --git a/tests/ovsdb-cluster.at b/tests/ovsdb-cluster.at
 index 3a0bd4579e..92aa427093 100644
 --- a/tests/ovsdb-cluster.at
@@ -44466,7 +45206,7 @@ index 3a0bd4579e..92aa427093 100644
          done=0
          for j in $(seq 0 $(expr $n1 - 1)); do
 diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
-index cc38d69c10..8a28dfe4ca 100644
+index cc38d69c10..d0feaa31fe 100644
 --- a/tests/ovsdb-idl.at
 +++ b/tests/ovsdb-idl.at
 @@ -12,25 +12,6 @@ ovsdb_start_idltest () {
@@ -44707,7 +45447,36 @@ index cc38d69c10..8a28dfe4ca 100644
  m4_define([OVSDB_CHECK_IDL_PARTIAL_UPDATE_SET_COLUMN],
    [AT_SETUP([$1 - C])
     AT_KEYWORDS([ovsdb server idl partial update set column positive $5])
-@@ -1764,33 +1898,25 @@ OVSDB_CHECK_IDL_COMPOUND_INDEX_WITH_REF([set, simple3 idl-compound-index-with-re
+@@ -1352,6 +1486,28 @@ m4_define([OVSDB_CHECK_IDL_NOTIFY],
+    [OVSDB_CHECK_IDL_PY([$1], [], [$2], [$3], [notify $4], [$5])
+     OVSDB_CHECK_IDL_SSL_PY([$1], [], [$2], [$3], [notify $4], [$5])])
+ 
++OVSDB_CHECK_IDL_NOTIFY([simple link idl verify notify],
++  [['track-notify' \
++    '["idltest",
++       {"op": "insert",
++       "table": "link1",
++       "row": {"i": 1, "k": ["named-uuid", "l1row"], "l2": ["set", [["named-uuid", "l2row"]]]},
++       "uuid-name": "l1row"},
++      {"op": "insert",
++       "table": "link2",
++       "uuid-name": "l2row",
++       "row": {"i": 2, "l1": ["set", [["named-uuid", "l1row"]]]}}]']],
++[[000: empty
++000: event:create, row={uuid=<0>}, updates=None
++000: event:create, row={uuid=<1>}, updates=None
++001: {"error":null,"result":[{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]}
++002: event:create, row={i=1 uuid=<2> l2=[<3>]}, updates=None
++002: event:create, row={i=2 uuid=<3> l1=[<2>]}, updates=None
++002: i=1 k=1 ka=[] l2=2 uuid=<2>
++002: i=2 l1=1 uuid=<3>
++003: done
++]])
++
+ OVSDB_CHECK_IDL_NOTIFY([simple idl verify notify],
+   [['track-notify' \
+     '["idltest",
+@@ -1764,33 +1920,25 @@ OVSDB_CHECK_IDL_COMPOUND_INDEX_WITH_REF([set, simple3 idl-compound-index-with-re
  ]])
  
  m4_define([CHECK_STREAM_OPEN_BLOCK],
@@ -44755,7 +45524,7 @@ index cc38d69c10..8a28dfe4ca 100644
  
  # same as OVSDB_CHECK_IDL but uses Python IDL implementation with tcp
  # with multiple remotes to assert the idl connects to the leader of the Raft cluster
-@@ -1798,7 +1924,7 @@ m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PY],
+@@ -1798,7 +1946,7 @@ m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PY],
    [AT_SETUP([$1 - Python3 (leader only)])
     AT_KEYWORDS([ovsdb server idl Python leader_only with tcp socket])
     m4_define([LPBK],[127.0.0.1])
@@ -44764,7 +45533,7 @@ index cc38d69c10..8a28dfe4ca 100644
     PARSE_LISTENING_PORT([s2.log], [TCP_PORT_1])
     PARSE_LISTENING_PORT([s3.log], [TCP_PORT_2])
     PARSE_LISTENING_PORT([s1.log], [TCP_PORT_3])
-@@ -1814,3 +1940,59 @@ m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PY],
+@@ -1814,3 +1962,59 @@ m4_define([OVSDB_CHECK_IDL_LEADER_ONLY_PY],
  
  OVSDB_CHECK_IDL_LEADER_ONLY_PY([Check Python IDL connects to leader], 3, ['remote'])
  OVSDB_CHECK_IDL_LEADER_ONLY_PY([Check Python IDL reconnects to leader], 3, ['remote' '+remotestop' 'remote'])
@@ -44860,6 +45629,23 @@ index 328ae2bc9d..49ac45275a 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/system-common-macros.at b/tests/system-common-macros.at
+index 68c8774d1a..9d5e24a292 100644
+--- a/tests/system-common-macros.at
++++ b/tests/system-common-macros.at
+@@ -275,6 +275,12 @@ m4_define([OVS_START_L7],
+    ]
+ )
+ 
++# OFPROTO_CLEAR_DURATION_IDLE([])
++#
++# Clear the duration from the piped input which would differ from test to test
++#
++m4_define([OFPROTO_CLEAR_DURATION_IDLE], [[sed -e 's/duration=.*s,/duration=<cleared>,/g' -e 's/idle_age=[0-9]*,/idle_age=<cleared>,/g']])
++
+ # OVS_CHECK_VXLAN()
+ #
+ # Do basic check for vxlan functionality, skip the test if it's not there.
 diff --git a/tests/system-route.at b/tests/system-route.at
 new file mode 100644
 index 0000000000..1714273e35
@@ -44895,7 +45681,7 @@ index 0000000000..1714273e35
 +OVS_TRAFFIC_VSWITCHD_STOP
 +AT_CLEANUP
 diff --git a/tests/system-traffic.at b/tests/system-traffic.at
-index 4a39c929c2..3ed03d92b5 100644
+index 4a39c929c2..da61e4cae8 100644
 --- a/tests/system-traffic.at
 +++ b/tests/system-traffic.at
 @@ -611,6 +611,16 @@ NS_CHECK_EXEC([at_ns0], [ping -q -c 3 10.1.1.100 | FORMAT_PING], [0], [dnl
@@ -44915,6 +45701,93 @@ index 4a39c929c2..3ed03d92b5 100644
  OVS_APP_EXIT_AND_WAIT([ovs-ofctl])
  OVS_TRAFFIC_VSWITCHD_STOP
  AT_CLEANUP
+@@ -2331,6 +2341,35 @@ NXST_FLOW reply:
+ OVS_TRAFFIC_VSWITCHD_STOP
+ AT_CLEANUP
+ 
++AT_SETUP([conntrack - generic IP protocol])
++CHECK_CONNTRACK()
++OVS_TRAFFIC_VSWITCHD_START()
++AT_CHECK([ovs-appctl vlog/set dpif:dbg dpif_netdev:dbg ofproto_dpif_upcall:dbg])
++
++ADD_NAMESPACES(at_ns0, at_ns1)
++
++ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
++ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
++
++AT_DATA([flows.txt], [dnl
++table=0, priority=1,action=drop
++table=0, priority=10,arp,action=normal
++table=0, priority=100,ip,action=ct(table=1)
++table=1, priority=100,in_port=1,ip,ct_state=+trk+new,action=ct(commit)
++table=1, priority=100,in_port=1,ct_state=+trk+est,action=normal
++])
++
++AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
++
++AT_CHECK([ovs-ofctl -O OpenFlow13 packet-out br0 "in_port=1 packet=01005e00001200005e000101080045c0002800000000ff7019cdc0a8001ee0000012210164010001ba52c0a800010000000000000000000000000000 actions=resubmit(,0)"])
++
++AT_CHECK([ovs-appctl dpctl/dump-conntrack | grep "orig=.src=192\.168\.0\.30,"], [], [dnl
++112,orig=(src=192.168.0.30,dst=224.0.0.18,sport=0,dport=0),reply=(src=224.0.0.18,dst=192.168.0.30,sport=0,dport=0)
++])
++
++OVS_TRAFFIC_VSWITCHD_STOP
++AT_CLEANUP
++
+ AT_SETUP([conntrack - ICMP related])
+ AT_SKIP_IF([test $HAVE_NC = no])
+ CHECK_CONNTRACK()
+@@ -5873,6 +5912,50 @@ ovs-appctl dpif/dump-flows br0
+ OVS_TRAFFIC_VSWITCHD_STOP
+ AT_CLEANUP
+ 
++AT_SETUP([conntrack - Multiple ICMP traverse])
++dnl This tracks sending ICMP packets via conntrack multiple times for the
++dnl same packet
++CHECK_CONNTRACK()
++OVS_TRAFFIC_VSWITCHD_START()
++OVS_CHECK_CT_CLEAR()
++
++ADD_NAMESPACES(at_ns0, at_ns1)
++ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24", "f0:00:00:01:01:01")
++ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24", "f0:00:00:01:01:02")
++dnl setup ct flows
++AT_DATA([flows.txt], [dnl
++table=0,priority=10  ip,icmp,ct_state=-trk action=ct(zone=1,table=1)
++table=0,priority=0   action=drop
++table=1,priority=10  ct_state=-est+trk+new,ip,ct_zone=1,in_port=1 action=ct(commit,table=2)
++table=1,priority=10  ct_state=+est-new+trk,ct_zone=1,in_port=1 action=resubmit(,2)
++table=1,priority=0   action=drop
++table=2,priority=10  ct_state=+trk+new,in_port=1 action=drop
++table=2,priority=10  ct_state=+trk+est action=drop
++])
++
++AT_CHECK([ovs-ofctl --bundle add-flows br0 flows.txt])
++
++# sending icmp pkts, first and second
++NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 1c 00 01 00 00 40 01 64 dc 0a 01 01 01 0a 01 01 02 08 00 f7 ff ff ff ff ff > /dev/null])
++
++NS_CHECK_EXEC([at_ns0], [$PYTHON3 $srcdir/sendpkt.py p0 f0 00 00 01 01 02 f0 00 00 01 01 01 08 00 45 00 00 1c 00 01 00 00 40 01 64 dc 0a 01 01 01 0a 01 01 02 08 00 f7 ff ff ff ff ff > /dev/null])
++
++sleep 1
++
++dnl ensure CT picked up the packet
++AT_CHECK([ovs-appctl dpctl/dump-conntrack | FORMAT_CT(10.1.1)], [0], [dnl
++icmp,orig=(src=10.1.1.1,dst=10.1.1.2,id=<cleared>,type=8,code=0),reply=(src=10.1.1.2,dst=10.1.1.1,id=<cleared>,type=0,code=0)
++])
++
++AT_CHECK([ovs-ofctl dump-flows br0 | grep table=2, | OFPROTO_CLEAR_DURATION_IDLE],
++         [0], [dnl
++ cookie=0x0, duration=<cleared>, table=2, n_packets=2, n_bytes=84, idle_age=<cleared>, priority=10,ct_state=+new+trk,in_port=1 actions=drop
++ cookie=0x0, duration=<cleared>, table=2, n_packets=0, n_bytes=0, idle_age=<cleared>, priority=10,ct_state=+est+trk actions=drop
++])
++
++OVS_TRAFFIC_VSWITCHD_STOP
++AT_CLEANUP
++
+ AT_BANNER([802.1ad])
+ 
+ AT_SETUP([802.1ad - vlan_limit])
 diff --git a/tests/system-userspace-packet-type-aware.at b/tests/system-userspace-packet-type-aware.at
 index c2246316de..974304758f 100644
 --- a/tests/system-userspace-packet-type-aware.at
@@ -45160,7 +46033,7 @@ index b1a4be36bb..31513c537f 100644
              } else {
                  print_idl(idl, step++);
 diff --git a/tests/test-ovsdb.py b/tests/test-ovsdb.py
-index 1b94b79a07..a196802743 100644
+index 1b94b79a07..9d3228f234 100644
 --- a/tests/test-ovsdb.py
 +++ b/tests/test-ovsdb.py
 @@ -28,6 +28,7 @@ import ovs.util
@@ -45171,17 +46044,31 @@ index 1b94b79a07..a196802743 100644
  from ovs.fatal_signal import signal_alarm
  
  vlog = ovs.vlog.Vlog("test-ovsdb")
-@@ -159,7 +160,8 @@ def get_simple_printable_row_string(row, columns):
+@@ -159,7 +160,10 @@ def get_simple_printable_row_string(row, columns):
                                           is ovs.db.data.Atom):
              value = getattr(row, column)
              if isinstance(value, dict):
 -                value = sorted(value.items())
 +                value = sorted((row_to_uuid(k), row_to_uuid(v))
 +                               for k, v in value.items())
++            if isinstance(value, (list, tuple)):
++                value = sorted((row_to_uuid(v) for v in value))
              s += "%s=%s " % (column, value)
      s = s.strip()
      s = re.sub('""|,|u?\'', "", s)
-@@ -212,6 +214,14 @@ def print_idl(idl, step):
+@@ -170,9 +174,10 @@ def get_simple_printable_row_string(row, columns):
+     return s
+ 
+ 
+-def get_simple_table_printable_row(row):
++def get_simple_table_printable_row(row, *additional_columns):
+     simple_columns = ["i", "r", "b", "s", "u", "ia",
+                       "ra", "ba", "sa", "ua", "uuid"]
++    simple_columns.extend(additional_columns)
+     return get_simple_printable_row_string(row, simple_columns)
+ 
+ 
+@@ -212,6 +217,14 @@ def print_idl(idl, step):
              print(s)
              n += 1
  
@@ -45196,7 +46083,7 @@ index 1b94b79a07..a196802743 100644
      if "link1" in idl.tables:
          l1 = idl.tables["link1"].rows
          for row in l1.values():
-@@ -303,6 +313,11 @@ def idltest_find_simple3(idl, i):
+@@ -303,6 +316,11 @@ def idltest_find_simple3(idl, i):
      return next(idl.index_equal("simple3", "simple3_by_name", i), None)
  
  
@@ -45208,7 +46095,7 @@ index 1b94b79a07..a196802743 100644
  def idl_set(idl, commands, step):
      txn = ovs.db.idl.Transaction(idl)
      increment = False
-@@ -524,6 +539,12 @@ def idl_set(idl, commands, step):
+@@ -524,6 +542,12 @@ def idl_set(idl, commands, step):
              setattr(new_row3, 'name', 'String3')
              new_row3.addvalue('uset', new_row41.uuid)
              assert len(getattr(new_row3, 'uset', [])) == 1
@@ -45221,6 +46108,16 @@ index 1b94b79a07..a196802743 100644
          else:
              sys.stderr.write("unknown command %s\n" % name)
              sys.exit(1)
+@@ -616,7 +640,8 @@ def do_idl(schema_file, remote, *commands):
+     def mock_notify(event, row, updates=None):
+         output = "%03d: " % step
+         output += "event:" + str(event) + ", row={"
+-        output += get_simple_table_printable_row(row) + "}, updates="
++        output += get_simple_table_printable_row(row,
++                                                 'l2', 'l1') + "}, updates="
+         if updates is None:
+             output += "None"
+         else:
 diff --git a/tests/test-reconnect.c b/tests/test-reconnect.c
 index 5a14e7fe58..bf0463e25c 100644
 --- a/tests/test-reconnect.c
@@ -45542,7 +46439,7 @@ index e55bfc2ed5..987d211069 100755
  
  
 diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
-index 8c5cd70327..d71c34e691 100644
+index 8c5cd70327..4156da20ef 100644
 --- a/utilities/ovs-ctl.in
 +++ b/utilities/ovs-ctl.in
 @@ -43,7 +43,8 @@ set_hostname () {
@@ -45555,7 +46452,15 @@ index 8c5cd70327..d71c34e691 100644
  }
  
  set_system_ids () {
-@@ -230,9 +231,14 @@ start_forwarding () {
+@@ -225,14 +226,21 @@ start_forwarding () {
+     if test X"$OVS_VSWITCHD" = Xyes; then
+         do_start_forwarding || return 1
+     fi
+-    set_hostname &
++    if test X"$RECORD_HOSTNAME" = Xyes; then
++        set_hostname &
++    fi
+     return 0
  }
  
  start_ovs_ipsec () {
@@ -45570,7 +46475,7 @@ index 8c5cd70327..d71c34e691 100644
          --log-file --detach --monitor unix:${rundir}/db.sock || return 1
      return 0
  }
-@@ -254,8 +260,7 @@ stop_forwarding () {
+@@ -254,8 +262,7 @@ stop_forwarding () {
  }
  
  stop_ovs_ipsec () {
@@ -45580,7 +46485,15 @@ index 8c5cd70327..d71c34e691 100644
  }
  
  ## --------------- ##
-@@ -341,6 +346,7 @@ set_defaults () {
+@@ -312,6 +319,7 @@ set_defaults () {
+     SYSTEM_ID=
+ 
+     FULL_HOSTNAME=yes
++    RECORD_HOSTNAME=yes
+ 
+     DELETE_BRIDGES=no
+     DELETE_TRANSIENT_PORTS=no
+@@ -341,6 +349,7 @@ set_defaults () {
      SPORT=
  
      IKE_DAEMON=
@@ -45588,7 +46501,54 @@ index 8c5cd70327..d71c34e691 100644
  
      type_file=$etcdir/system-type.conf
      version_file=$etcdir/system-version.conf
-@@ -424,6 +430,8 @@ Options for "enable-protocol":
+@@ -372,19 +381,24 @@ This program is intended to be invoked internally by Open vSwitch startup
+ scripts.  System administrators should not normally invoke it directly.
+ 
+ Commands:
+-  start                   start Open vSwitch daemons
+-  stop                    stop Open vSwitch daemons
+-  restart                 stop and start Open vSwitch daemons
+-  status                  check whether Open vSwitch daemons are running
+-  version                 print versions of Open vSwitch daemons
+-  load-kmod               insert modules if not already present
+-  force-reload-kmod       save OVS network device state, stop OVS, unload kernel
+-                          module, reload kernel module, start OVS, restore state
+-  enable-protocol         enable protocol specified in options with iptables
+-  delete-transient-ports  delete transient (other_config:transient=true) ports
+-  start-ovs-ipsec         start Open vSwitch ipsec daemon
+-  stop-ovs-ipsec          stop Open vSwitch ipsec daemon
+-  help                    display this help message
++  start                       start Open vSwitch daemons
++  stop                        stop Open vSwitch daemons
++  restart                     stop and start Open vSwitch daemons
++  status                      check whether Open vSwitch daemons are running
++  version                     print versions of Open vSwitch daemons
++  load-kmod                   insert modules if not already present
++  force-reload-kmod           save OVS network device state, stop OVS, unload
++                              kernel module, reload kernel module, start OVS,
++                              restore state
++  enable-protocol             enable protocol specified in options with
++                              iptables
++  delete-transient-ports      delete transient (other_config:transient=true)
++                              ports
++  start-ovs-ipsec             start Open vSwitch ipsec daemon
++  stop-ovs-ipsec              stop Open vSwitch ipsec daemon
++  record-hostname-if-not-set  determine the system hostname and record it in
++                              the Open vSwitch database if not already set
++  help                        display this help message
+ 
+ One of the following options is required for "start", "restart" and "force-reload-kmod":
+   --system-id=UUID   set specific ID to uniquely identify this system
+@@ -405,6 +419,8 @@ Less important options for "start", "restart" and "force-reload-kmod":
+   --ovsdb-server-priority=NICE   set ovsdb-server's niceness (default: $OVSDB_SERVER_PRIORITY)
+   --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default: $OVS_VSWITCHD_PRIORITY)
+   --no-full-hostname             set short hostname instead of full hostname
++  --no-record-hostname           do not attempt to determine/record system
++                                 hostname as part of start command
+ 
+ Debugging options for "start", "restart" and "force-reload-kmod":
+   --ovsdb-server-wrapper=WRAPPER
+@@ -424,6 +440,8 @@ Options for "enable-protocol":
  Option for "start-ovs-ipsec":
    --ike-daemon=IKE_DAEMON
        the IKE daemon for ipsec tunnels (either libreswan or strongswan)
@@ -45597,6 +46557,16 @@ index 8c5cd70327..d71c34e691 100644
  
  Other options:
    -h, --help                  display this help message
+@@ -561,6 +579,9 @@ case $command in
+     stop-ovs-ipsec)
+         stop_ovs_ipsec
+         ;;
++    record-hostname-if-not-set)
++        set_hostname
++        ;;
+     help)
+         usage
+         ;;
 diff --git a/utilities/ovs-dev.py b/utilities/ovs-dev.py
 index 248d22ab9a..c45788acd5 100755
 --- a/utilities/ovs-dev.py
@@ -45728,7 +46698,7 @@ index e591c26a6c..ce348b9d16 100644
  }
  
 diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
-index 3ddaaefda8..9f07ec9b22 100644
+index 3ddaaefda8..11880f1d2f 100644
 --- a/vswitchd/vswitch.xml
 +++ b/vswitchd/vswitch.xml
 @@ -653,8 +653,9 @@
@@ -45776,6 +46746,37 @@ index 3ddaaefda8..9f07ec9b22 100644
        <column name="other_config" key="userspace-tso-enable"
                type='{"type": "boolean"}'>
          <p>
+@@ -2971,8 +2998,8 @@
+       <group title="Tunnel Options: IPsec">
+         <p>
+           Setting any of these options enables IPsec support for a given
+-          tunnel.  <code>gre</code>, <code>ip6gre</code>,
+-          <code>geneve</code>, <code>vxlan</code> and <code>stt</code>
++          tunnel.  <code>gre</code>, <code>geneve</code>,
++          <code>vxlan</code> and <code>stt</code>
+           interfaces support these options.  See the <code>IPsec</code>
+           section in the <ref table="Open_vSwitch"/> table for a description
+           of each mode.
+@@ -4530,7 +4557,8 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
+         packets per second the CIR would be set to to to 46000000. This value
+         can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing
+         rate for the number of packets per second and 46 represents the size
+-        of the packet data for a 64 byte ip packet.
++        of the packet data for a 64 bytes IP packet without 14 bytes Ethernet
++        and 4 bytes FCS header.
+       </column>
+       <column name="other_config" key="cbs" type='{"type": "integer"}'>
+         The Committed Burst Size (CBS) is measured in bytes and represents a
+@@ -4551,7 +4579,8 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
+         packets per second the EIR would be set to to to 46000000. This value
+         can be broken into '1,000,000 x 46'. Where 1,000,000 is the policing
+         rate for the number of packets per second and 46 represents the size
+-        of the packet data for a 64 byte ip packet.
++        of the packet data for a 64 bytes IP packet without 14 bytes Ethernet
++        and 4 bytes FCS header.
+       </column>
+       <column name="other_config" key="ebs" type='{"type": "integer"}'>
+         The Excess Burst Size (EBS) is measured in bytes and represents a
 diff --git a/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update b/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update
 index e7404e3b00..b8db881949 100755
 --- a/xenserver/etc_xapi.d_plugins_openvswitch-cfg-update
diff --git a/SPECS/openvswitch2.13.spec b/SPECS/openvswitch2.13.spec
index 0dfc738..1cca3d4 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: 79.5.1%{?commit0:.%{date}git%{shortcommit0}}%{?commit1:dpdk%{shortcommit1}}%{?dist}
+Release: 96%{?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
@@ -332,7 +332,14 @@ make V=1 O=%{dpdktarget} T=%{dpdktarget} %{?_smp_mflags} config
 cp -f %{SOURCE500} %{SOURCE502} "%{_sourcedir}/%{dpdktarget}-config" .
 %{SOURCE502} %{dpdktarget}-config "%{dpdktarget}/.config"
 
-make V=1 O=%{dpdktarget} %{?_smp_mflags}
+# Currently RHEL8.3+ includes binutils 2.30 with the patch to fix AVX512 support backported (#1870039),
+# but DPDK 19.11 blindly disables AVX512 support if ld version < 2.32
+binutils_version=$(rpm -q --qf '%%{version}-%%{release}' binutils)
+if [ "$binutils_version" "<" "2.30-79.el8" ]; then
+    make V=1 O=%{dpdktarget} %{?_smp_mflags}
+else
+    make LD_VERSION=2.32 V=1 O=%{dpdktarget} %{?_smp_mflags}
+fi
 
 # Generate a list of supported drivers, its hard to tell otherwise.
 cat << EOF > README.DPDK-PMDS
@@ -703,25 +710,73 @@ exit 0
 %endif
 
 %changelog
-* Thu Feb 04 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-79.5
-- lldp: do not leak memory on multiple instances of TLVs
-  [5a1158c1bbca87260491048219d08189b2367797]
+* Tue Mar 16 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-96
+- Merging upstream branch-2.13
+  [bb107a7f7f27a7f3ad77cebc15049606e63568c2]
+
+* Mon Feb 15 2021 Eelco Chaudron <echaudro@redhat.com> - 2.13.0-95
+- conntrack: add generic IP protocol support
+  [6b3ca4b0282bb6e728066004fca47a0936e4b8c3]
 
-* Thu Feb 04 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-79.4
-- flow: Support extra padding length.
-  [c9ada1e1249d7729954c4154f0cc7bd375f40686]
+* Wed Feb 10 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-94
+- Merging upstream branch-2.13
+  [8655a639ac7db93d02e3cd003cf5ae4f7acad10a]
+
+* Fri Feb 05 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-93
+- Merging upstream branch-2.13
+  [2100324b58f204f956a35e9827d2d72e4d20b7d9]
 
-* Tue Feb 02 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-79.3
+* Thu Feb 04 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-92
+- Merging upstream branch-2.13
+  [92b77d14894afeb17d2b139e75670aaa29853511]
+
+* Wed Feb 03 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-91
+- Merging upstream branch-2.13
+  [ea87c21ff21477eff945b07a755329f05d4466b7]
+
+* Tue Feb 02 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-90
 - dpif-netdev: Add PMD auto load balance status log.
-  [793de3fd0a2b32dc7f45d4e9f01daa419b144013]
+  [4fd540d8efc8369c6af05e5e266bf418afade8d3]
 
-* Tue Feb 02 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-79.2
+* Tue Feb 02 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-89
 - dpif-netdev: Add parameters to configure PMD auto load balance.
-  [75555d8352c7151ec5dd02653ac820229775caf2]
+  [5935f7a9d8754ff0b5fadbc835c65dea9cdf1434]
 
-* Tue Feb 02 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-79.1
+* Tue Feb 02 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-88
 - dpif-netdev: Add log for PMD auto load balance interval parameter.
-  [f22c01de8773a60069e2371fb110fc207756dcd4]
+  [a8f4696c200ee9f1786b66fe6c7d7da4caa9924c]
+
+* Mon Feb 01 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-87
+- Merging upstream branch-2.13
+  [d303f53850951fa26f6a832ffb2f437fcd4cf9f1]
+
+* Fri Jan 29 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-86
+- Merging upstream branch-2.13
+  [2986e0866ea3d2c5e9a4b4fd43e81e1477c03686]
+
+* Thu Jan 28 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-85
+- Merging upstream branch-2.13
+  [f2f6b58dd9df37438da9c7ef902decd613c787d6]
+
+* Thu Jan 28 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-84
+- redhat: Use a mock config based on the buildsystem target
+  [b820a7b8946c64749284b88538399dd2f9b411fe]
+
+* Thu Jan 28 2021 Flavio Leitner <fbl@redhat.com> - 2.13.0-83
+- Merging b37528cef7 conntrack: Fix the icmp conntrack new state.
+  [dc913c7d4c23e792d4077c81bc65c025bc4c5f6c]
+
+* Thu Jan 28 2021 Flavio Leitner <fbl@redhat.com> - 2.13.0-82
+- Merging f383000ca6 acinclude: Strip out -mno-avx512f provided ..
+  [304ba372e44e1f930d6a2134140db415d8d56922]
+
+* Wed Jan 20 2021 Timothy Redaelli <tredaelli@redhat.com> - 2.13.0-81
+- Enable AVX512 support on binutils >= 2.30-79.el8
+  [8b3f9929026f45837b5670fade0ffde616fde5bc]
+
+* Thu Jan 14 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-80
+- Merging upstream branch-2.13
+  [b7a6e48410649f2d0029baaf499a5cf0619f4f34]
 
 * Wed Jan 06 2021 Open vSwitch CI <ovs-team@redhat.com> - 2.13.0-79
 - Merging upstream branch-2.13