Open vSwitch CI dda1f5
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
Open vSwitch CI dda1f5
index 724e3e2f0f..d90b9273a6 100644
Open vSwitch CI dda1f5
--- a/.github/workflows/build-and-test.yml
Open vSwitch CI dda1f5
+++ b/.github/workflows/build-and-test.yml
Open vSwitch CI dda1f5
@@ -610,7 +610,7 @@ jobs:
Open vSwitch CI dda1f5
   build-linux-rpm:
Open vSwitch CI dda1f5
     name: linux rpm fedora
Open vSwitch CI dda1f5
     runs-on: ubuntu-latest
Open vSwitch CI dda1f5
-    container: fedora:39
Open vSwitch CI dda1f5
+    container: fedora:41
Open vSwitch CI dda1f5
     timeout-minutes: 30
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
     strategy:
Open vSwitch CI 993944
diff --git a/AUTHORS.rst b/AUTHORS.rst
Open vSwitch CI 993944
index 05c2fb7046..8454641758 100644
Open vSwitch CI 993944
--- a/AUTHORS.rst
Open vSwitch CI 993944
+++ b/AUTHORS.rst
Open vSwitch CI 993944
@@ -312,6 +312,7 @@ Mark Kavanagh                      mark.b.kavanagh81@gmail.com
Open vSwitch CI 993944
 Mark Maglana                       mmaglana@gmail.com
Open vSwitch CI 993944
 Mark Michelson                     mmichels@redhat.com
Open vSwitch CI 993944
 Markos Chandras                    mchandras@suse.de
Open vSwitch CI 993944
+Markus Linnala                     markus.linnala@gmail.com
Open vSwitch CI 993944
 Martin Casado                      casado@cs.stanford.edu
Open vSwitch CI 993944
 Martin Fong                        mwfong@csl.sri.com
Open vSwitch CI 993944
 Martin Kalcok                      martin.kalcok@canonical.com
Open vSwitch CI 70cc8f
diff --git a/Documentation/faq/releases.rst b/Documentation/faq/releases.rst
Open vSwitch CI 9bf6b6
index c9acc1e80e..1368f52b84 100644
Open vSwitch CI 70cc8f
--- a/Documentation/faq/releases.rst
Open vSwitch CI 70cc8f
+++ b/Documentation/faq/releases.rst
Open vSwitch CI 9bf6b6
@@ -216,12 +216,13 @@ Q: What DPDK version does each Open vSwitch release work with?
Open vSwitch CI 9bf6b6
     2.14.x       19.11.13
Open vSwitch CI 9bf6b6
     2.15.x       20.11.6
Open vSwitch CI 9bf6b6
     2.16.x       20.11.6
Open vSwitch CI 9bf6b6
-    2.17.x       21.11.8
Open vSwitch CI 9bf6b6
-    3.0.x        21.11.8
Open vSwitch CI 9bf6b6
-    3.1.x        22.11.6
Open vSwitch CI 9bf6b6
-    3.2.x        22.11.6
Open vSwitch CI 9bf6b6
-    3.3.x        23.11.2
Open vSwitch CI 9bf6b6
-    3.4.x        23.11.2
Open vSwitch CI 9bf6b6
+    2.17.x       21.11.9
Open vSwitch CI 9bf6b6
+    3.0.x        21.11.9
Open vSwitch CI 9bf6b6
+    3.1.x        22.11.7
Open vSwitch CI 9bf6b6
+    3.2.x        22.11.7
Open vSwitch CI 9bf6b6
+    3.3.x        23.11.3
Open vSwitch CI 9bf6b6
+    3.4.x        23.11.3
Open vSwitch CI 70cc8f
+    3.5.x        24.11.1
Open vSwitch CI 70cc8f
     ============ ========
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 Q: Are all the DPDK releases that OVS versions work with maintained?
Open vSwitch CI 56d821
diff --git a/Documentation/intro/install/general.rst b/Documentation/intro/install/general.rst
Open vSwitch CI 56d821
index 42b7172891..0f3cb4e496 100644
Open vSwitch CI 56d821
--- a/Documentation/intro/install/general.rst
Open vSwitch CI 56d821
+++ b/Documentation/intro/install/general.rst
Open vSwitch CI 56d821
@@ -166,7 +166,7 @@ other than plain text, only if you have the following:
Open vSwitch CI 56d821
 If you are going to extensively modify Open vSwitch, consider installing the
Open vSwitch CI 56d821
 following to obtain better warnings:
Open vSwitch CI 56d821
 
Open vSwitch CI 56d821
-- "sparse" version 0.6.2 or later
Open vSwitch CI 56d821
+- "sparse" version 0.6.4 or later
Open vSwitch CI 56d821
   (https://git.kernel.org/pub/scm/devel/sparse/sparse.git/).
Open vSwitch CI 56d821
 
Open vSwitch CI 56d821
 - GNU make.
Open vSwitch CI dda1f5
diff --git a/Documentation/ref/ovs-flowviz.8.rst b/Documentation/ref/ovs-flowviz.8.rst
Open vSwitch CI dda1f5
index e8d84d995e..54adff498a 100644
Open vSwitch CI dda1f5
--- a/Documentation/ref/ovs-flowviz.8.rst
Open vSwitch CI dda1f5
+++ b/Documentation/ref/ovs-flowviz.8.rst
Open vSwitch CI dda1f5
@@ -52,7 +52,7 @@ them in one of the predefined *format*\ s.
Open vSwitch CI dda1f5
 Options
Open vSwitch CI dda1f5
 =======
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
-.. program: ovs-flowviz
Open vSwitch CI dda1f5
+.. program:: ovs-flowviz
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
 .. option:: -h, --help
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
@@ -151,6 +151,8 @@ option.
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
 Arguments:
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
+.. program:: ovs-flowviz [datapath|openflow] console
Open vSwitch CI dda1f5
+
Open vSwitch CI dda1f5
 .. option:: -h, --heat-map
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
    Color of the packet and byte counters to reflect their relative size.
Open vSwitch CI dda1f5
@@ -201,6 +203,8 @@ A logical block is a set of flows that have:
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
 Arguments:
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
+.. program:: ovs-flowviz openflow logic
Open vSwitch CI dda1f5
+
Open vSwitch CI dda1f5
 .. option:: -s, --show-flows
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
     Show all the flows under each logical block.
Open vSwitch CI dda1f5
@@ -277,6 +281,8 @@ same tree-like flow hierarchy that the ``tree`` format prints.
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
 Arguments:
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
+.. program:: ovs-flowviz datapath console
Open vSwitch CI dda1f5
+
Open vSwitch CI dda1f5
 .. option:: -h, --html
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
     Print the graphviz format as an svg image alongside an interactive HTML
Open vSwitch CI dda1f5
diff --git a/Documentation/ref/ovs-sim.1.rst b/Documentation/ref/ovs-sim.1.rst
Open vSwitch CI dda1f5
index f59cd7af7a..60971de3c7 100644
Open vSwitch CI dda1f5
--- a/Documentation/ref/ovs-sim.1.rst
Open vSwitch CI dda1f5
+++ b/Documentation/ref/ovs-sim.1.rst
Open vSwitch CI dda1f5
@@ -58,7 +58,7 @@ such privileges.
Open vSwitch CI dda1f5
 Options
Open vSwitch CI dda1f5
 =======
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
-.. program: ovs-sim
Open vSwitch CI dda1f5
+.. program:: ovs-sim
Open vSwitch CI dda1f5
 
Open vSwitch CI dda1f5
 *script*
Open vSwitch CI dda1f5
     Runs *script*, which should be a Bash script, within a subshell
Open vSwitch CI 70cc8f
diff --git a/Documentation/topics/userspace-tso.rst b/Documentation/topics/userspace-tso.rst
Open vSwitch CI 70cc8f
index ae08496bdd..ed4d36edd1 100644
Open vSwitch CI 70cc8f
--- a/Documentation/topics/userspace-tso.rst
Open vSwitch CI 70cc8f
+++ b/Documentation/topics/userspace-tso.rst
Open vSwitch CI 70cc8f
@@ -109,9 +109,9 @@ then started again. OvS will then report::
Open vSwitch CI 70cc8f
 Limitations
Open vSwitch CI 70cc8f
 ~~~~~~~~~~~
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-The current OvS userspace `TSO` implementation supports flat and VLAN networks
Open vSwitch CI 70cc8f
-only (i.e. no support for `TSO` over tunneled connection [VxLAN, GRE, IPinIP,
Open vSwitch CI 70cc8f
-etc.]).
Open vSwitch CI 70cc8f
+The current OvS userspace `TSO` implementation supports flat, VLAN networks,
Open vSwitch CI 70cc8f
+and some tunneled connections.  Currently only VxLAN, Geneve and GRE tunnels
Open vSwitch CI 70cc8f
+are supported.
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 The NIC driver must support and advertise checksum offload for TCP and UDP.
Open vSwitch CI 70cc8f
 However, SCTP is not mandatory because very few drivers advertised support
Open vSwitch CI 70cc8f
@@ -120,11 +120,11 @@ in Open vSwitch. Currently, if the NIC supports that, then the feature is
Open vSwitch CI 70cc8f
 enabled, otherwise TSO can still be enabled but SCTP packets sent to the NIC
Open vSwitch CI 70cc8f
 will be dropped.
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-There is no software implementation of TSO, so all ports attached to the
Open vSwitch CI 70cc8f
-datapath must support TSO or packets using that feature will be dropped
Open vSwitch CI 70cc8f
-on ports without TSO support.  That also means guests using vhost-user
Open vSwitch CI 70cc8f
-in client mode will receive TSO packet regardless of TSO being enabled
Open vSwitch CI 70cc8f
-or disabled within the guest.
Open vSwitch CI 70cc8f
+There is a limited software implementation of TSO when tunnels are used which
Open vSwitch CI 70cc8f
+only supports VxLAN, Geneve, and GRE.  When these tunnels are used with TSO,
Open vSwitch CI 70cc8f
+not all ports attached to the datapath need to support hardware TSO.
Open vSwitch CI 70cc8f
+Guests using vhost-user in client mode will receive TSO packet regardless of
Open vSwitch CI 70cc8f
+TSO being enabled or disabled within the guest.
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 All kernel devices that use the raw socket interface (veth, for example)
Open vSwitch CI 70cc8f
 require the kernel commit 9d2f67e43b73 ("net/packet: fix packet drop as of
Open vSwitch CI 70cc8f
diff --git a/Makefile.am b/Makefile.am
Open vSwitch CI 70cc8f
index dc5c34a6ae..a61a1cadfb 100644
Open vSwitch CI 70cc8f
--- a/Makefile.am
Open vSwitch CI 70cc8f
+++ b/Makefile.am
Open vSwitch CI 70cc8f
@@ -339,6 +339,8 @@ check-tabs:
Open vSwitch CI 70cc8f
 	fi
Open vSwitch CI 70cc8f
 .PHONY: check-tabs
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+# NOTE: test-lib-route-table.c excluded due to use of system() to execute
Open vSwitch CI 70cc8f
+#       ip route commands provided as arguments by test suite.
Open vSwitch CI 70cc8f
 ALL_LOCAL += thread-safety-check
Open vSwitch CI 70cc8f
 thread-safety-check:
Open vSwitch CI 70cc8f
 	@cd $(srcdir); \
Open vSwitch CI 70cc8f
@@ -346,7 +348,8 @@ thread-safety-check:
Open vSwitch CI 70cc8f
 	  grep -n -f build-aux/thread-safety-forbidden \
Open vSwitch CI 70cc8f
 	    `git ls-files | grep '\.[ch]$$' \
Open vSwitch CI 70cc8f
 	      | $(EGREP) -v '^datapath-windows|^lib/sflow|^third-party'` /dev/null \
Open vSwitch CI 70cc8f
-	      | $(EGREP) -v ':[ 	]*/?\*'; \
Open vSwitch CI 70cc8f
+	      | $(EGREP) -v ':[ 	]*/?\*' \
Open vSwitch CI 70cc8f
+	      | $(EGREP) -v '^tests/test-lib-route-table.c'; \
Open vSwitch CI 70cc8f
 	then \
Open vSwitch CI 70cc8f
 	  echo "See above for list of calls to functions that are"; \
Open vSwitch CI 70cc8f
 	  echo "forbidden due to thread safety issues"; \
Open vSwitch CI 70cc8f
diff --git a/NEWS b/NEWS
Open vSwitch CI 70cc8f
index 83f0513797..ec2f85c015 100644
Open vSwitch CI 70cc8f
--- a/NEWS
Open vSwitch CI 70cc8f
+++ b/NEWS
Open vSwitch CI 70cc8f
@@ -1,4 +1,4 @@
Open vSwitch CI 70cc8f
-Post-v3.4.0
Open vSwitch CI 70cc8f
+v3.5.0 - xx xxx xxxx
Open vSwitch CI 70cc8f
 --------------------
Open vSwitch CI 70cc8f
    - The limit on the number of fields for address prefix tracking in flow
Open vSwitch CI 70cc8f
      tables increased from 3 to 4.  For example, it is now possible to
Open vSwitch CI 70cc8f
@@ -31,6 +31,8 @@ Post-v3.4.0
Open vSwitch CI 70cc8f
        that does not have a specific value defined, rather than being
Open vSwitch CI 70cc8f
        treated as a global value, aligning the behavior with that of
Open vSwitch CI 70cc8f
        the kernel datapath.
Open vSwitch CI 70cc8f
+     * Extended the support for TSO software fallback to include support for
Open vSwitch CI 70cc8f
+       VXLAN, Geneve, and GRE tunneled packets.
Open vSwitch CI 70cc8f
    - Linux TC offload:
Open vSwitch CI 70cc8f
      * Add support for matching tunnel flags if the kernel supports it.
Open vSwitch CI 70cc8f
      * Add support for the "Don't Fragment" (DF) flag in the encap action,
Open vSwitch CI 70cc8f
@@ -55,6 +57,8 @@ Post-v3.4.0
Open vSwitch CI 70cc8f
        to make it not configure any crypto options (ike/esp) for connections.
Open vSwitch CI 70cc8f
        Most useful in combination with '--root-ipsec-conf' where system-wide
Open vSwitch CI 70cc8f
        crypto-policy is included from the root ipsec.conf.
Open vSwitch CI 70cc8f
+     * New option '--ovs-monitor-ipsec-options' for 'ovs-ctl start-ovs-ipsec'
Open vSwitch CI 70cc8f
+       to pass above new options to ovs-monitor-ipsec.
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 v3.4.0 - 15 Aug 2024
Open vSwitch CI 70cc8f
diff --git a/configure.ac b/configure.ac
Open vSwitch CI 70cc8f
index 266e9d4799..2b19888775 100644
Open vSwitch CI 70cc8f
--- a/configure.ac
Open vSwitch CI 70cc8f
+++ b/configure.ac
Open vSwitch CI 70cc8f
@@ -13,7 +13,7 @@
Open vSwitch CI 70cc8f
 # limitations under the License.
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 AC_PREREQ(2.63)
Open vSwitch CI 70cc8f
-AC_INIT(openvswitch, 3.4.90, bugs@openvswitch.org)
Open vSwitch CI 70cc8f
+AC_INIT(openvswitch, 3.5.0, bugs@openvswitch.org)
Open vSwitch CI 70cc8f
 AC_CONFIG_SRCDIR([vswitchd/ovs-vswitchd.c])
Open vSwitch CI 70cc8f
 AC_CONFIG_MACRO_DIR([m4])
Open vSwitch CI 70cc8f
 AC_CONFIG_AUX_DIR([build-aux])
Open vSwitch CI 70cc8f
diff --git a/debian/automake.mk b/debian/automake.mk
Open vSwitch CI 70cc8f
index fe8febdd3c..7ae4e00e58 100644
Open vSwitch CI 70cc8f
--- a/debian/automake.mk
Open vSwitch CI 70cc8f
+++ b/debian/automake.mk
Open vSwitch CI 70cc8f
@@ -14,6 +14,8 @@ EXTRA_DIST += \
Open vSwitch CI 70cc8f
 	debian/openvswitch-common.lintian-overrides \
Open vSwitch CI 70cc8f
 	debian/openvswitch-doc.doc-base \
Open vSwitch CI 70cc8f
 	debian/openvswitch-doc.install \
Open vSwitch CI 70cc8f
+	debian/openvswitch-ipsec.default \
Open vSwitch CI 70cc8f
+	debian/openvswitch-ipsec.dirs \
Open vSwitch CI 70cc8f
 	debian/openvswitch-ipsec.init \
Open vSwitch CI 70cc8f
 	debian/openvswitch-ipsec.install \
Open vSwitch CI 70cc8f
 	debian/openvswitch-ipsec.service \
Open vSwitch CI 70cc8f
@@ -56,8 +58,6 @@ EXTRA_DIST += \
Open vSwitch CI 70cc8f
 	debian/openvswitch-vtep.init \
Open vSwitch CI 70cc8f
 	debian/openvswitch-vtep.install \
Open vSwitch CI 70cc8f
 	debian/ovs-systemd-reload \
Open vSwitch CI 70cc8f
-	debian/patches/ovs-ctl-ipsec.patch \
Open vSwitch CI 70cc8f
-	debian/patches/series \
Open vSwitch CI 70cc8f
 	debian/python3-openvswitch.install \
Open vSwitch CI 70cc8f
 	debian/rules \
Open vSwitch CI 70cc8f
 	debian/source/format \
Open vSwitch CI 70cc8f
diff --git a/debian/changelog b/debian/changelog
Open vSwitch CI 70cc8f
index f1a071141d..3f4e2c56e3 100644
Open vSwitch CI 70cc8f
--- a/debian/changelog
Open vSwitch CI 70cc8f
+++ b/debian/changelog
Open vSwitch CI 70cc8f
@@ -1,8 +1,8 @@
Open vSwitch CI 70cc8f
-openvswitch (3.4.90-1) unstable; urgency=low
Open vSwitch CI 70cc8f
+openvswitch (3.5.0-1) unstable; urgency=low
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
    * New upstream version
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
- -- Open vSwitch team <dev@openvswitch.org>  Mon, 15 Jul 2024 13:00:01 +0100
Open vSwitch CI 70cc8f
+ -- Open vSwitch team <dev@openvswitch.org>  Mon, 16 Jan 2025 13:00:01 +0100
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 openvswitch (3.4.0-1) unstable; urgency=low
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
diff --git a/debian/control.in b/debian/control.in
Open vSwitch CI 70cc8f
index 47b1f8cdd6..dfcf10bcc4 100644
Open vSwitch CI 70cc8f
--- a/debian/control.in
Open vSwitch CI 70cc8f
+++ b/debian/control.in
Open vSwitch CI 70cc8f
@@ -39,14 +39,17 @@ Rules-Requires-Root: no
Open vSwitch CI 70cc8f
 Homepage: http://openvswitch.org/
Open vSwitch CI 70cc8f
 Vcs-Browser: https://salsa.debian.org/openstack-team/third-party/openvswitch/-/tree/debian/experimental
Open vSwitch CI 70cc8f
 Vcs-Git: https://salsa.debian.org/openstack-team/third-party/openvswitch.git
Open vSwitch CI 70cc8f
+X-Python3-Version: >= 3.10
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 Package: openvswitch-common
Open vSwitch CI 70cc8f
 Architecture: linux-any
Open vSwitch CI 70cc8f
 Depends:
Open vSwitch CI 70cc8f
  openssl,
Open vSwitch CI 70cc8f
  ${misc:Depends},
Open vSwitch CI 70cc8f
- ${python3:Depends},
Open vSwitch CI 70cc8f
  ${shlibs:Depends},
Open vSwitch CI 70cc8f
+Recommends:
Open vSwitch CI 70cc8f
+ python3-openvswitch (= ${binary:Version}),
Open vSwitch CI 70cc8f
+ ${python3:Depends},
Open vSwitch CI 70cc8f
 Suggests:
Open vSwitch CI 70cc8f
  ethtool,
Open vSwitch CI 70cc8f
  openvswitch-doc,
Open vSwitch CI 70cc8f
@@ -94,7 +97,6 @@ Depends:
Open vSwitch CI 70cc8f
  python3-openvswitch (= ${source:Version}),
Open vSwitch CI 70cc8f
  strongswan,
Open vSwitch CI 70cc8f
  ${misc:Depends},
Open vSwitch CI 70cc8f
- ${shlibs:Depends},
Open vSwitch CI 70cc8f
 Suggests: python3:any
Open vSwitch CI 70cc8f
 Breaks:
Open vSwitch CI 70cc8f
  openvswitch-common (<< 2.17~),
Open vSwitch CI 70cc8f
@@ -154,12 +156,13 @@ Depends:
Open vSwitch CI 70cc8f
  netbase,
Open vSwitch CI 70cc8f
  openvswitch-common (= ${binary:Version}),
Open vSwitch CI 70cc8f
  procps,
Open vSwitch CI 70cc8f
- python3-netifaces,
Open vSwitch CI 70cc8f
- python3-openvswitch (>= ${source:Version}),
Open vSwitch CI 70cc8f
  uuid-runtime,
Open vSwitch CI 70cc8f
  ${misc:Depends},
Open vSwitch CI 70cc8f
- ${python3:Depends},
Open vSwitch CI 70cc8f
  ${shlibs:Depends},
Open vSwitch CI 70cc8f
+Recommends:
Open vSwitch CI 70cc8f
+ python3-netifaces,
Open vSwitch CI 70cc8f
+ python3-openvswitch (>= ${source:Version}),
Open vSwitch CI 70cc8f
+ ${python3:Depends},
Open vSwitch CI 70cc8f
 Breaks:
Open vSwitch CI 70cc8f
  openvswitch-common (<< 2.17~),
Open vSwitch CI 70cc8f
 Replaces:
Open vSwitch CI 70cc8f
@@ -183,7 +186,6 @@ Description: Open vSwitch switch implementations
Open vSwitch CI 70cc8f
 # DPDK_NETDEV  dpdk,
Open vSwitch CI 70cc8f
 # DPDK_NETDEV  openvswitch-switch (= ${binary:Version}),
Open vSwitch CI 70cc8f
 # DPDK_NETDEV  ${misc:Depends},
Open vSwitch CI 70cc8f
-# DPDK_NETDEV  ${python3:Depends},
Open vSwitch CI 70cc8f
 # DPDK_NETDEV  ${shlibs:Depends},
Open vSwitch CI 70cc8f
 # DPDK_NETDEV Enhances:
Open vSwitch CI 70cc8f
 # DPDK_NETDEV  openvswitch-switch,
Open vSwitch CI 70cc8f
@@ -258,7 +260,6 @@ Depends:
Open vSwitch CI 70cc8f
  openvswitch-switch (>= ${binary:Version}),
Open vSwitch CI 70cc8f
  python3-openvswitch (>= ${source:Version}),
Open vSwitch CI 70cc8f
  ${misc:Depends},
Open vSwitch CI 70cc8f
- ${python3:Depends},
Open vSwitch CI 70cc8f
  ${shlibs:Depends},
Open vSwitch CI 70cc8f
 Suggests: python3:any
Open vSwitch CI 70cc8f
 Breaks:
Open vSwitch CI 70cc8f
@@ -284,12 +285,13 @@ Depends:
Open vSwitch CI 70cc8f
  ${misc:Depends},
Open vSwitch CI 70cc8f
  ${python3:Depends},
Open vSwitch CI 70cc8f
  ${shlibs:Depends},
Open vSwitch CI 70cc8f
-Suggests:
Open vSwitch CI 70cc8f
+Recommends:
Open vSwitch CI 70cc8f
  python3-click,
Open vSwitch CI 70cc8f
- python3-graphviz,
Open vSwitch CI 70cc8f
  python3-netaddr,
Open vSwitch CI 70cc8f
  python3-pyparsing,
Open vSwitch CI 70cc8f
  python3-rich,
Open vSwitch CI 70cc8f
+Suggests:
Open vSwitch CI 70cc8f
+ python3-graphviz,
Open vSwitch CI 70cc8f
  python3-unbound,
Open vSwitch CI 70cc8f
 Description: Python 3 bindings for Open vSwitch
Open vSwitch CI 70cc8f
  Open vSwitch is a production quality, multilayer, software-based,
Open vSwitch CI 70cc8f
diff --git a/debian/openvswitch-common.install b/debian/openvswitch-common.install
Open vSwitch CI 70cc8f
index 9bdb43a6f2..5fef8de74e 100644
Open vSwitch CI 70cc8f
--- a/debian/openvswitch-common.install
Open vSwitch CI 70cc8f
+++ b/debian/openvswitch-common.install
Open vSwitch CI 70cc8f
@@ -1,6 +1,7 @@
Open vSwitch CI 70cc8f
 etc/bash_completion.d/ovs-appctl-bashcomp.bash usr/share/bash-completion/completions
Open vSwitch CI 70cc8f
 usr/bin/ovs-appctl
Open vSwitch CI 70cc8f
 usr/bin/ovs-docker
Open vSwitch CI 70cc8f
+usr/bin/ovs-flowviz
Open vSwitch CI 70cc8f
 usr/bin/ovs-ofctl
Open vSwitch CI 70cc8f
 usr/bin/ovs-parse-backtrace
Open vSwitch CI 70cc8f
 usr/bin/ovs-pki
Open vSwitch CI 70cc8f
@@ -20,6 +21,7 @@ usr/share/man/man7/ovsdb-server.7
Open vSwitch CI 70cc8f
 usr/share/man/man7/ovsdb.7
Open vSwitch CI 70cc8f
 usr/share/man/man8/ovs-appctl.8
Open vSwitch CI 70cc8f
 usr/share/man/man8/ovs-bugtool.8
Open vSwitch CI 70cc8f
+usr/share/man/man8/ovs-flowviz.8
Open vSwitch CI 70cc8f
 usr/share/man/man8/ovs-ofctl.8
Open vSwitch CI 70cc8f
 usr/share/man/man8/ovs-parse-backtrace.8
Open vSwitch CI 70cc8f
 usr/share/man/man8/ovs-pki.8
Open vSwitch CI 70cc8f
diff --git a/debian/openvswitch-ipsec.default b/debian/openvswitch-ipsec.default
Open vSwitch CI 70cc8f
new file mode 100644
Open vSwitch CI 70cc8f
index 0000000000..a074948591
Open vSwitch CI 70cc8f
--- /dev/null
Open vSwitch CI 70cc8f
+++ b/debian/openvswitch-ipsec.default
Open vSwitch CI 70cc8f
@@ -0,0 +1,5 @@
Open vSwitch CI 70cc8f
+# This is a POSIX shell fragment                -*- sh -*-
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+# OVS_CTL_OPTS: Extra options to pass to ovs-ctl.  This is, for example,
Open vSwitch CI 70cc8f
+# a suitable place to specify --no-restart-ike-daemon.
Open vSwitch CI 70cc8f
+# OVS_CTL_OPTS=
Open vSwitch CI 70cc8f
diff --git a/debian/openvswitch-ipsec.dirs b/debian/openvswitch-ipsec.dirs
Open vSwitch CI 70cc8f
new file mode 100644
Open vSwitch CI 70cc8f
index 0000000000..4b83f29661
Open vSwitch CI 70cc8f
--- /dev/null
Open vSwitch CI 70cc8f
+++ b/debian/openvswitch-ipsec.dirs
Open vSwitch CI 70cc8f
@@ -0,0 +1 @@
Open vSwitch CI 70cc8f
+/usr/share/openvswitch/ipsec
Open vSwitch CI 70cc8f
diff --git a/debian/openvswitch-ipsec.init b/debian/openvswitch-ipsec.init
Open vSwitch CI 70cc8f
index aa68384547..4fc7701b83 100755
Open vSwitch CI 70cc8f
--- a/debian/openvswitch-ipsec.init
Open vSwitch CI 70cc8f
+++ b/debian/openvswitch-ipsec.init
Open vSwitch CI 70cc8f
@@ -41,6 +41,8 @@ test -x $DAEMON || exit 0
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 . /lib/lsb/init-functions
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+test -e /etc/default/openvswitch-ipsec && . /etc/default/openvswitch-ipsec
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 DODTIME=10              # Time to wait for the server to die, in seconds
Open vSwitch CI 70cc8f
                         # If this value is set too low you might not
Open vSwitch CI 70cc8f
                         # let some servers to die gracefully and
Open vSwitch CI 70cc8f
@@ -72,7 +74,8 @@ running() {
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 start_server() {
Open vSwitch CI 70cc8f
-    ${DATADIR}/scripts/ovs-ctl --ike-daemon=strongswan start-ovs-ipsec
Open vSwitch CI 70cc8f
+    ${DATADIR}/scripts/ovs-ctl --ike-daemon=strongswan \
Open vSwitch CI 70cc8f
+        start-ovs-ipsec $OVS_CTL_OPTS
Open vSwitch CI 70cc8f
     return 0
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
diff --git a/debian/openvswitch-ipsec.install b/debian/openvswitch-ipsec.install
Open vSwitch CI 70cc8f
old mode 100644
Open vSwitch CI 70cc8f
new mode 100755
Open vSwitch CI 70cc8f
index 31a8945e2f..ae127e2d4d
Open vSwitch CI 70cc8f
--- a/debian/openvswitch-ipsec.install
Open vSwitch CI 70cc8f
+++ b/debian/openvswitch-ipsec.install
Open vSwitch CI 70cc8f
@@ -1 +1,3 @@
Open vSwitch CI 70cc8f
+#!/usr/bin/dh-exec
Open vSwitch CI 70cc8f
+debian/openvswitch-ipsec.default => /usr/share/openvswitch/ipsec/default.template
Open vSwitch CI 70cc8f
 usr/share/openvswitch/scripts/ovs-monitor-ipsec
Open vSwitch CI 70cc8f
diff --git a/debian/openvswitch-ipsec.service b/debian/openvswitch-ipsec.service
Open vSwitch CI 70cc8f
index 608a6a6188..2f92def514 100644
Open vSwitch CI 70cc8f
--- a/debian/openvswitch-ipsec.service
Open vSwitch CI 70cc8f
+++ b/debian/openvswitch-ipsec.service
Open vSwitch CI 70cc8f
@@ -6,8 +6,10 @@ After=openvswitch-switch.service
Open vSwitch CI 70cc8f
 [Service]
Open vSwitch CI 70cc8f
 Type=forking
Open vSwitch CI 70cc8f
 PIDFile=/run/openvswitch/ovs-monitor-ipsec.pid
Open vSwitch CI 70cc8f
-ExecStart=/usr/share/openvswitch/scripts/ovs-ctl \
Open vSwitch CI 70cc8f
-                    --ike-daemon=strongswan start-ovs-ipsec
Open vSwitch CI 70cc8f
+Restart=on-failure
Open vSwitch CI 70cc8f
+EnvironmentFile=-/etc/default/openvswitch-ipsec
Open vSwitch CI 70cc8f
+ExecStart=/usr/share/openvswitch/scripts/ovs-ctl --no-monitor \
Open vSwitch CI 70cc8f
+                    --ike-daemon=strongswan start-ovs-ipsec $OVS_CTL_OPTS
Open vSwitch CI 70cc8f
 ExecStop=/usr/share/openvswitch/scripts/ovs-ctl stop-ovs-ipsec
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 [Install]
Open vSwitch CI 70cc8f
diff --git a/debian/openvswitch-switch.ovs-vswitchd.service b/debian/openvswitch-switch.ovs-vswitchd.service
Open vSwitch CI 70cc8f
index 519d80d8ed..a4d445b953 100644
Open vSwitch CI 70cc8f
--- a/debian/openvswitch-switch.ovs-vswitchd.service
Open vSwitch CI 70cc8f
+++ b/debian/openvswitch-switch.ovs-vswitchd.service
Open vSwitch CI 70cc8f
@@ -11,6 +11,7 @@ DefaultDependencies=no
Open vSwitch CI 70cc8f
 [Service]
Open vSwitch CI 70cc8f
 LimitNOFILE=1048576
Open vSwitch CI 70cc8f
 Type=forking
Open vSwitch CI 70cc8f
+PIDFile=/run/openvswitch/ovs-vswitchd.pid
Open vSwitch CI 70cc8f
 Restart=on-failure
Open vSwitch CI 70cc8f
 Environment=HOME=/var/run/openvswitch
Open vSwitch CI 70cc8f
 EnvironmentFile=-/etc/default/openvswitch-switch
Open vSwitch CI 70cc8f
diff --git a/debian/openvswitch-switch.ovsdb-server.service b/debian/openvswitch-switch.ovsdb-server.service
Open vSwitch CI 70cc8f
index 339665b255..35654d7059 100644
Open vSwitch CI 70cc8f
--- a/debian/openvswitch-switch.ovsdb-server.service
Open vSwitch CI 70cc8f
+++ b/debian/openvswitch-switch.ovsdb-server.service
Open vSwitch CI 70cc8f
@@ -8,6 +8,7 @@ DefaultDependencies=no
Open vSwitch CI 70cc8f
 [Service]
Open vSwitch CI 70cc8f
 LimitNOFILE=1048576
Open vSwitch CI 70cc8f
 Type=forking
Open vSwitch CI 70cc8f
+PIDFile=/run/openvswitch/ovsdb-server.pid
Open vSwitch CI 70cc8f
 Restart=on-failure
Open vSwitch CI 70cc8f
 EnvironmentFile=-/etc/default/openvswitch-switch
Open vSwitch CI 70cc8f
 ExecStart=/usr/share/openvswitch/scripts/ovs-ctl \
Open vSwitch CI 70cc8f
@@ -18,6 +19,3 @@ ExecStop=/usr/share/openvswitch/scripts/ovs-ctl --no-ovs-vswitchd stop
Open vSwitch CI 70cc8f
 ExecReload=/usr/share/openvswitch/scripts/ovs-ctl --no-ovs-vswitchd \
Open vSwitch CI 70cc8f
           --no-record-hostname \
Open vSwitch CI 70cc8f
           --no-monitor restart $OVS_CTL_OPTS
Open vSwitch CI 70cc8f
-RuntimeDirectory=openvswitch
Open vSwitch CI 70cc8f
-RuntimeDirectoryMode=0755
Open vSwitch CI 70cc8f
-RuntimeDirectoryPreserve=yes
Open vSwitch CI 70cc8f
diff --git a/debian/openvswitch-test.install b/debian/openvswitch-test.install
Open vSwitch CI 70cc8f
index 88c8252805..dfc8ebf302 100644
Open vSwitch CI 70cc8f
--- a/debian/openvswitch-test.install
Open vSwitch CI 70cc8f
+++ b/debian/openvswitch-test.install
Open vSwitch CI 70cc8f
@@ -2,4 +2,5 @@ usr/bin/ovs-l3ping
Open vSwitch CI 70cc8f
 usr/bin/ovs-test
Open vSwitch CI 70cc8f
 usr/share/man/man8/ovs-l3ping.8
Open vSwitch CI 70cc8f
 usr/share/man/man8/ovs-test.8
Open vSwitch CI 70cc8f
+usr/share/openvswitch/python/ovstest usr/lib/python3/dist-packages/
Open vSwitch CI 70cc8f
 usr/share/openvswitch/scripts/usdt/*
Open vSwitch CI 70cc8f
diff --git a/debian/patches/ovs-ctl-ipsec.patch b/debian/patches/ovs-ctl-ipsec.patch
Open vSwitch CI 70cc8f
deleted file mode 100644
Open vSwitch CI 70cc8f
index 63375cd47d..0000000000
Open vSwitch CI 70cc8f
--- a/debian/patches/ovs-ctl-ipsec.patch
Open vSwitch CI 70cc8f
+++ /dev/null
Open vSwitch CI 70cc8f
@@ -1,18 +0,0 @@
Open vSwitch CI 70cc8f
-Description: Don't monitor ipsec daemon
Open vSwitch CI 70cc8f
- For Ubuntu systemd will monitor the ovs-monitor-ipsec daemon so
Open vSwitch CI 70cc8f
- there is no need to spawn a separate monitor thread to deal with
Open vSwitch CI 70cc8f
- restarts.  Doing so has the side effect of confusing systemd into
Open vSwitch CI 70cc8f
- monitoring the wrong process.
Open vSwitch CI 70cc8f
-Author: James Page <james.page@ubuntu.com>
Open vSwitch CI 70cc8f
-Forwarded: not-needed
Open vSwitch CI 70cc8f
-
Open vSwitch CI 70cc8f
---- a/utilities/ovs-ctl.in
Open vSwitch CI 70cc8f
-+++ b/utilities/ovs-ctl.in
Open vSwitch CI 70cc8f
-@@ -245,7 +245,7 @@ start_ovs_ipsec () {
Open vSwitch CI 70cc8f
-         --pidfile=${rundir}/ovs-monitor-ipsec.pid \
Open vSwitch CI 70cc8f
-         --ike-daemon=$IKE_DAEMON \
Open vSwitch CI 70cc8f
-         $no_restart \
Open vSwitch CI 70cc8f
--        --log-file --detach --monitor unix:${rundir}/db.sock || return 1
Open vSwitch CI 70cc8f
-+        --log-file --detach unix:${rundir}/db.sock || return 1
Open vSwitch CI 70cc8f
-     return 0
Open vSwitch CI 70cc8f
- }
Open vSwitch CI 70cc8f
diff --git a/debian/patches/series b/debian/patches/series
Open vSwitch CI 70cc8f
deleted file mode 100644
Open vSwitch CI 70cc8f
index 87a2a1d97c..0000000000
Open vSwitch CI 70cc8f
--- a/debian/patches/series
Open vSwitch CI 70cc8f
+++ /dev/null
Open vSwitch CI 70cc8f
@@ -1 +0,0 @@
Open vSwitch CI 70cc8f
-ovs-ctl-ipsec.patch
Open vSwitch CI 70cc8f
diff --git a/debian/python3-openvswitch.install b/debian/python3-openvswitch.install
Open vSwitch CI 70cc8f
index e1e8c3a6e1..cd1dae3aff 100644
Open vSwitch CI 70cc8f
--- a/debian/python3-openvswitch.install
Open vSwitch CI 70cc8f
+++ b/debian/python3-openvswitch.install
Open vSwitch CI 70cc8f
@@ -1 +1,6 @@
Open vSwitch CI 70cc8f
-usr/share/man/man8/ovs-flowviz.8
Open vSwitch CI 70cc8f
+# At the dh_install stage we need to retain python version specific directory
Open vSwitch CI 70cc8f
+# tree to support extensions.
Open vSwitch CI 70cc8f
+#
Open vSwitch CI 70cc8f
+# dh_python will consolidate into usr/lib/python3/dist-packages retaining
Open vSwitch CI 70cc8f
+# version specific shared object files.
Open vSwitch CI 70cc8f
+usr/lib/python3* usr/lib/
Open vSwitch CI 70cc8f
diff --git a/debian/rules b/debian/rules
Open vSwitch CI 70cc8f
index b6f905f3cd..6b51b51e16 100755
Open vSwitch CI 70cc8f
--- a/debian/rules
Open vSwitch CI 70cc8f
+++ b/debian/rules
Open vSwitch CI 70cc8f
@@ -16,7 +16,6 @@ else
Open vSwitch CI 70cc8f
 PARALLEL =
Open vSwitch CI 70cc8f
 endif
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-PYTHON3S:=$(shell py3versions -vr)
Open vSwitch CI 70cc8f
 DEB_HOST_ARCH?=$(shell dpkg-architecture -qDEB_HOST_ARCH)
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 override_dh_auto_configure:
Open vSwitch CI 70cc8f
@@ -80,9 +79,26 @@ endif # nodpdk
Open vSwitch CI 70cc8f
 endif # i386/amd64/ppc64el
Open vSwitch CI 70cc8f
 endif # nocheck
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+export PYBUILD_DESTDIR = $(CURDIR)/debian/tmp
Open vSwitch CI 70cc8f
+export PYBUILD_DIR = $(CURDIR)/python
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+pybuild = \
Open vSwitch CI 70cc8f
+	export PKG_CONFIG_PATH=$(CURDIR)/debian/tmp/usr/lib/pkgconfig; \
Open vSwitch CI 70cc8f
+	export PKG_CONFIG_SYSROOT_DIR=$(CURDIR)/debian/tmp; \
Open vSwitch CI 70cc8f
+	export PKG_CONFIG_SYSTEM_INCLUDE_PATH=/; \
Open vSwitch CI 70cc8f
+	export PKG_CONFIG_SYSTEM_LIBRARY_PATH=/; \
Open vSwitch CI 70cc8f
+	enable_shared=no \
Open vSwitch CI 70cc8f
+	extra_cflags="`pkg-config --cflags libopenvswitch`" \
Open vSwitch CI 70cc8f
+	extra_libs="-Wl,-Bstatic -lopenvswitch -Wl,-Bdynamic `pkg-config --libs --static libopenvswitch`" \
Open vSwitch CI 70cc8f
+	pybuild
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 override_dh_auto_build:
Open vSwitch CI 70cc8f
 	dh_auto_build --sourcedirectory=_debian -- dist distdir=openvswitch
Open vSwitch CI 70cc8f
 	dh_auto_build --sourcedirectory=_debian
Open vSwitch CI 70cc8f
+	# We need an extra install here so that we can use pkgconfig to
Open vSwitch CI 70cc8f
+	# retrieve accurate CFLAGS and LDFLAGS for building Python extensions.
Open vSwitch CI 70cc8f
+	dh_auto_install --sourcedirectory=_debian
Open vSwitch CI 70cc8f
+	$(pybuild) --build
Open vSwitch CI 70cc8f
 ifneq (,$(filter i386 amd64 ppc64el arm64, $(DEB_HOST_ARCH)))
Open vSwitch CI 70cc8f
 ifeq (,$(filter nodpdk, $(DEB_BUILD_OPTIONS)))
Open vSwitch CI 70cc8f
 	dh_auto_build --sourcedirectory=_dpdk
Open vSwitch CI 70cc8f
@@ -91,28 +107,15 @@ endif
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 execute_before_dh_auto_clean:
Open vSwitch CI 70cc8f
 	find . -name "*.pyc" -delete
Open vSwitch CI 70cc8f
+	if test -d $(PYBUILD_DIR)/build; then \
Open vSwitch CI 70cc8f
+		pybuild --clean ; \
Open vSwitch CI 70cc8f
+	fi
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 override_dh_auto_install:
Open vSwitch CI 70cc8f
+	# We need to use pybuild to install Python extensions.
Open vSwitch CI 70cc8f
+	$(pybuild) --install
Open vSwitch CI 70cc8f
 	dh_auto_install --sourcedirectory=_debian
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-execute_after_dh_install:
Open vSwitch CI 70cc8f
-	set -e && for pyvers in $(PYTHON3S); do \
Open vSwitch CI 70cc8f
-		cd python; \
Open vSwitch CI 70cc8f
-		export PKG_CONFIG_PATH=$(CURDIR)/debian/tmp/usr/lib/pkgconfig; \
Open vSwitch CI 70cc8f
-		export PKG_CONFIG_SYSROOT_DIR=$(CURDIR)/debian/tmp; \
Open vSwitch CI 70cc8f
-		export PKG_CONFIG_SYSTEM_INCLUDE_PATH=/; \
Open vSwitch CI 70cc8f
-		export PKG_CONFIG_SYSTEM_LIBRARY_PATH=/; \
Open vSwitch CI 70cc8f
-		enable_shared=no \
Open vSwitch CI 70cc8f
-		extra_cflags="`pkg-config --cflags libopenvswitch`" \
Open vSwitch CI 70cc8f
-		extra_libs="-Wl,-Bstatic -lopenvswitch -Wl,-Bdynamic `pkg-config --libs --static libopenvswitch`" \
Open vSwitch CI 70cc8f
-		python$$pyvers setup.py install --install-layout=deb \
Open vSwitch CI 70cc8f
-			--root $(CURDIR)/debian/python3-openvswitch; \
Open vSwitch CI 70cc8f
-		cd ..; \
Open vSwitch CI 70cc8f
-		mkdir -p $(CURDIR)/debian/openvswitch-test/usr/lib/python$$pyvers/dist-packages/ovstest; \
Open vSwitch CI 70cc8f
-		install -v -D python/ovstest/*.py \
Open vSwitch CI 70cc8f
-			$(CURDIR)/debian/openvswitch-test/usr/lib/python$$pyvers/dist-packages/ovstest; \
Open vSwitch CI 70cc8f
-	done
Open vSwitch CI 70cc8f
-
Open vSwitch CI 70cc8f
 override_dh_installinit:
Open vSwitch CI 70cc8f
 	dh_installinit --restart-after-upgrade
Open vSwitch CI 70cc8f
 	dh_installinit -popenvswitch-switch --name=ovsdb-server --no-start
Open vSwitch CI 70cc8f
@@ -134,8 +137,8 @@ override_dh_python3:
Open vSwitch CI 70cc8f
 # Helper target for creating snapshots from upstream git
Open vSwitch CI 70cc8f
 DATE=$(shell date +%Y%m%d)
Open vSwitch CI 70cc8f
 # Upstream branch to track
Open vSwitch CI 70cc8f
-BRANCH=branch-3.4
Open vSwitch CI 70cc8f
-VERSION=3.4.0
Open vSwitch CI 70cc8f
+BRANCH=branch-3.5
Open vSwitch CI 70cc8f
+VERSION=3.5.0
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 get-orig-snapshot:
Open vSwitch CI 70cc8f
 	rm -Rf openvswitch-upstream
Open vSwitch CI 70cc8f
diff --git a/include/openvswitch/ofp-ct.h b/include/openvswitch/ofp-ct.h
Open vSwitch CI 70cc8f
index d57b626784..ea68c2e605 100644
Open vSwitch CI 70cc8f
--- a/include/openvswitch/ofp-ct.h
Open vSwitch CI 70cc8f
+++ b/include/openvswitch/ofp-ct.h
Open vSwitch CI 70cc8f
@@ -24,6 +24,8 @@
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 #include "openflow/nicira-ext.h"
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+struct ds;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 #ifdef __cplusplus
Open vSwitch CI 70cc8f
 extern "C" {
Open vSwitch CI 70cc8f
 #endif
Open vSwitch CI 56d821
diff --git a/include/sparse/automake.mk b/include/sparse/automake.mk
Open vSwitch CI 56d821
index 45e6202c52..052a1b4b82 100644
Open vSwitch CI 56d821
--- a/include/sparse/automake.mk
Open vSwitch CI 56d821
+++ b/include/sparse/automake.mk
Open vSwitch CI 56d821
@@ -12,10 +12,7 @@ noinst_HEADERS += \
Open vSwitch CI 56d821
         include/sparse/netinet/ip6.h \
Open vSwitch CI 56d821
         include/sparse/netpacket/packet.h \
Open vSwitch CI 56d821
         include/sparse/pthread.h \
Open vSwitch CI 56d821
-        include/sparse/rte_atomic.h \
Open vSwitch CI 56d821
-        include/sparse/rte_mbuf.h \
Open vSwitch CI 56d821
         include/sparse/rte_memcpy.h \
Open vSwitch CI 56d821
-        include/sparse/rte_trace_point.h \
Open vSwitch CI 56d821
         include/sparse/sys/socket.h \
Open vSwitch CI 56d821
         include/sparse/sys/sysmacros.h \
Open vSwitch CI 56d821
         include/sparse/sys/types.h \
Open vSwitch CI 56d821
diff --git a/include/sparse/rte_atomic.h b/include/sparse/rte_atomic.h
Open vSwitch CI 56d821
deleted file mode 100644
Open vSwitch CI 56d821
index ae49fe5c03..0000000000
Open vSwitch CI 56d821
--- a/include/sparse/rte_atomic.h
Open vSwitch CI 56d821
+++ /dev/null
Open vSwitch CI 56d821
@@ -1,25 +0,0 @@
Open vSwitch CI 56d821
-/* Copyright (c) 2015 Nicira, Inc.
Open vSwitch CI 56d821
- *
Open vSwitch CI 56d821
- * Licensed under the Apache License, Version 2.0 (the "License");
Open vSwitch CI 56d821
- * you may not use this file except in compliance with the License.
Open vSwitch CI 56d821
- * You may obtain a copy of the License at:
Open vSwitch CI 56d821
- *
Open vSwitch CI 56d821
- *     http://www.apache.org/licenses/LICENSE-2.0
Open vSwitch CI 56d821
- *
Open vSwitch CI 56d821
- * Unless required by applicable law or agreed to in writing, software
Open vSwitch CI 56d821
- * distributed under the License is distributed on an "AS IS" BASIS,
Open vSwitch CI 56d821
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Open vSwitch CI 56d821
- * See the License for the specific language governing permissions and
Open vSwitch CI 56d821
- * limitations under the License.
Open vSwitch CI 56d821
- */
Open vSwitch CI 56d821
-
Open vSwitch CI 56d821
-#ifndef __CHECKER__
Open vSwitch CI 56d821
-#error "Use this header only with sparse.  It is not a correct implementation."
Open vSwitch CI 56d821
-#endif
Open vSwitch CI 56d821
-
Open vSwitch CI 56d821
-/* Fix sparse technicality about types in one of the function calls by just
Open vSwitch CI 56d821
- * ignoring it. */
Open vSwitch CI 56d821
-#define __sync_add_and_fetch(a, b) (0)
Open vSwitch CI 56d821
-
Open vSwitch CI 56d821
-/* Get actual <rte_atomic.h> definitions for us to annotate and build on. */
Open vSwitch CI 56d821
-#include_next <rte_atomic.h>
Open vSwitch CI 56d821
diff --git a/include/sparse/rte_mbuf.h b/include/sparse/rte_mbuf.h
Open vSwitch CI 56d821
deleted file mode 100644
Open vSwitch CI 56d821
index 981cdb441f..0000000000
Open vSwitch CI 56d821
--- a/include/sparse/rte_mbuf.h
Open vSwitch CI 56d821
+++ /dev/null
Open vSwitch CI 56d821
@@ -1,29 +0,0 @@
Open vSwitch CI 56d821
-/* Copyright (c) 2020 Intel, Inc.
Open vSwitch CI 56d821
- *
Open vSwitch CI 56d821
- * Licensed under the Apache License, Version 2.0 (the "License");
Open vSwitch CI 56d821
- * you may not use this file except in compliance with the License.
Open vSwitch CI 56d821
- * You may obtain a copy of the License at:
Open vSwitch CI 56d821
- *
Open vSwitch CI 56d821
- *     http://www.apache.org/licenses/LICENSE-2.0
Open vSwitch CI 56d821
- *
Open vSwitch CI 56d821
- * Unless required by applicable law or agreed to in writing, software
Open vSwitch CI 56d821
- * distributed under the License is distributed on an "AS IS" BASIS,
Open vSwitch CI 56d821
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Open vSwitch CI 56d821
- * See the License for the specific language governing permissions and
Open vSwitch CI 56d821
- * limitations under the License.
Open vSwitch CI 56d821
- */
Open vSwitch CI 56d821
-
Open vSwitch CI 56d821
-#ifndef __CHECKER__
Open vSwitch CI 56d821
-#error "Use this header only with sparse.  It is not a correct implementation."
Open vSwitch CI 56d821
-#endif
Open vSwitch CI 56d821
-
Open vSwitch CI 56d821
-/* sparse doesn't know about gcc atomic builtins. */
Open vSwitch CI 56d821
-#ifndef __ATOMIC_ACQ_REL
Open vSwitch CI 56d821
-#define __ATOMIC_ACQ_REL 0
Open vSwitch CI 56d821
-#define __ATOMIC_RELAXED 1
Open vSwitch CI 56d821
-#define __atomic_add_fetch(p, val, memorder) (*(p) = *(p) + (val))
Open vSwitch CI 56d821
-#define __atomic_store_n(p, val, memorder) (*(p) = (val))
Open vSwitch CI 56d821
-#endif
Open vSwitch CI 56d821
-
Open vSwitch CI 56d821
-/* Get actual <rte_mbuf.h> definitions for us to annotate and build on. */
Open vSwitch CI 56d821
-#include_next <rte_mbuf.h>
Open vSwitch CI 56d821
diff --git a/include/sparse/rte_trace_point.h b/include/sparse/rte_trace_point.h
Open vSwitch CI 56d821
deleted file mode 100644
Open vSwitch CI 56d821
index 8039232754..0000000000
Open vSwitch CI 56d821
--- a/include/sparse/rte_trace_point.h
Open vSwitch CI 56d821
+++ /dev/null
Open vSwitch CI 56d821
@@ -1,28 +0,0 @@
Open vSwitch CI 56d821
-/* Copyright 2020, Red Hat, Inc.
Open vSwitch CI 56d821
- *
Open vSwitch CI 56d821
- * Licensed under the Apache License, Version 2.0 (the "License");
Open vSwitch CI 56d821
- * you may not use this file except in compliance with the License.
Open vSwitch CI 56d821
- * You may obtain a copy of the License at:
Open vSwitch CI 56d821
- *
Open vSwitch CI 56d821
- *     http://www.apache.org/licenses/LICENSE-2.0
Open vSwitch CI 56d821
- *
Open vSwitch CI 56d821
- * Unless required by applicable law or agreed to in writing, software
Open vSwitch CI 56d821
- * distributed under the License is distributed on an "AS IS" BASIS,
Open vSwitch CI 56d821
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Open vSwitch CI 56d821
- * See the License for the specific language governing permissions and
Open vSwitch CI 56d821
- * limitations under the License.
Open vSwitch CI 56d821
- */
Open vSwitch CI 56d821
-
Open vSwitch CI 56d821
-#ifndef __CHECKER__
Open vSwitch CI 56d821
-#error "Use this header only with sparse.  It is not a correct implementation."
Open vSwitch CI 56d821
-#endif
Open vSwitch CI 56d821
-
Open vSwitch CI 56d821
-/* sparse doesn't know about gcc atomic builtins. */
Open vSwitch CI 56d821
-#ifndef __ATOMIC_ACQUIRE
Open vSwitch CI 56d821
-#define __ATOMIC_ACQUIRE 0
Open vSwitch CI 56d821
-#define __atomic_load_n(p, memorder) *(p)
Open vSwitch CI 56d821
-#endif
Open vSwitch CI 56d821
-
Open vSwitch CI 56d821
-/* Get actual <rte_trace_point.h> definitions for us to annotate and
Open vSwitch CI 56d821
- * build on. */
Open vSwitch CI 56d821
-#include_next <rte_trace_point.h>
Open vSwitch CI 70cc8f
diff --git a/lib/dp-packet-gso.c b/lib/dp-packet-gso.c
Open vSwitch CI 70cc8f
index 04ebb19da1..2356359772 100644
Open vSwitch CI 70cc8f
--- a/lib/dp-packet-gso.c
Open vSwitch CI 70cc8f
+++ b/lib/dp-packet-gso.c
Open vSwitch CI 70cc8f
@@ -73,8 +73,7 @@ dp_packet_gso_nr_segs(struct dp_packet *p)
Open vSwitch CI 70cc8f
     const char *data_tail;
Open vSwitch CI 70cc8f
     const char *data_pos;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-    if (dp_packet_hwol_is_tunnel_vxlan(p) ||
Open vSwitch CI 70cc8f
-        dp_packet_hwol_is_tunnel_geneve(p)) {
Open vSwitch CI 70cc8f
+    if (dp_packet_hwol_is_tunnel(p)) {
Open vSwitch CI 70cc8f
         data_pos = dp_packet_get_inner_tcp_payload(p);
Open vSwitch CI 70cc8f
     } else {
Open vSwitch CI 70cc8f
         data_pos = dp_packet_get_tcp_payload(p);
Open vSwitch CI 70cc8f
@@ -105,7 +104,9 @@ dp_packet_gso(struct dp_packet *p, struct dp_packet_batch **batches)
Open vSwitch CI 70cc8f
     bool outer_ipv4;
Open vSwitch CI 70cc8f
     int hdr_len;
Open vSwitch CI 70cc8f
     int seg_len;
Open vSwitch CI 70cc8f
-    bool tnl;
Open vSwitch CI 70cc8f
+    bool udp_tnl = dp_packet_hwol_is_tunnel_vxlan(p) ||
Open vSwitch CI 70cc8f
+                   dp_packet_hwol_is_tunnel_geneve(p);
Open vSwitch CI 70cc8f
+    bool gre_tnl = dp_packet_hwol_is_tunnel_gre(p);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     tso_segsz = dp_packet_get_tso_segsz(p);
Open vSwitch CI 70cc8f
     if (!tso_segsz) {
Open vSwitch CI 70cc8f
@@ -114,11 +115,9 @@ dp_packet_gso(struct dp_packet *p, struct dp_packet_batch **batches)
Open vSwitch CI 70cc8f
         return false;
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-    if (dp_packet_hwol_is_tunnel_vxlan(p) ||
Open vSwitch CI 70cc8f
-        dp_packet_hwol_is_tunnel_geneve(p)) {
Open vSwitch CI 70cc8f
+    if (udp_tnl || gre_tnl) {
Open vSwitch CI 70cc8f
         outer_ipv4 = dp_packet_hwol_is_outer_ipv4(p);
Open vSwitch CI 70cc8f
         tcp_hdr = dp_packet_inner_l4(p);
Open vSwitch CI 70cc8f
-        tnl = true;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
         if (outer_ipv4) {
Open vSwitch CI 70cc8f
             outer_ip_id = ntohs(((struct ip_header *) dp_packet_l3(p))->ip_id);
Open vSwitch CI 70cc8f
@@ -130,7 +129,6 @@ dp_packet_gso(struct dp_packet *p, struct dp_packet_batch **batches)
Open vSwitch CI 70cc8f
     } else {
Open vSwitch CI 70cc8f
         outer_ipv4 = dp_packet_hwol_is_ipv4(p);
Open vSwitch CI 70cc8f
         tcp_hdr = dp_packet_l4(p);
Open vSwitch CI 70cc8f
-        tnl = false;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
         if (outer_ipv4) {
Open vSwitch CI 70cc8f
             struct ip_header *ip_hdr = dp_packet_l3(p);
Open vSwitch CI 70cc8f
@@ -156,13 +154,15 @@ dp_packet_gso(struct dp_packet *p, struct dp_packet_batch **batches)
Open vSwitch CI 70cc8f
         seg = dp_packet_gso_seg_new(p, hdr_len, data_pos, seg_len);
Open vSwitch CI 70cc8f
         data_pos += seg_len;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-        if (tnl) {
Open vSwitch CI 70cc8f
+        if (udp_tnl) {
Open vSwitch CI 70cc8f
             /* Update tunnel UDP header length. */
Open vSwitch CI 70cc8f
             struct udp_header *tnl_hdr;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
             tnl_hdr = dp_packet_l4(seg);
Open vSwitch CI 70cc8f
             tnl_hdr->udp_len = htons(dp_packet_l4_size(seg));
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+        if (udp_tnl || gre_tnl) {
Open vSwitch CI 70cc8f
             /* Update tunnel inner L3 header. */
Open vSwitch CI 70cc8f
             if (dp_packet_hwol_is_ipv4(seg)) {
Open vSwitch CI 70cc8f
                 struct ip_header *ip_hdr = dp_packet_inner_l3(seg);
Open vSwitch CI 70cc8f
@@ -194,7 +194,7 @@ dp_packet_gso(struct dp_packet *p, struct dp_packet_batch **batches)
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
         /* Update L4 header. */
Open vSwitch CI 70cc8f
-        if (tnl) {
Open vSwitch CI 70cc8f
+        if (udp_tnl || gre_tnl) {
Open vSwitch CI 70cc8f
             tcp_hdr = dp_packet_inner_l4(seg);
Open vSwitch CI 70cc8f
         } else {
Open vSwitch CI 70cc8f
             tcp_hdr = dp_packet_l4(seg);
Open vSwitch CI 70cc8f
@@ -208,6 +208,18 @@ dp_packet_gso(struct dp_packet *p, struct dp_packet_batch **batches)
Open vSwitch CI 70cc8f
             tcp_hdr->tcp_ctl = TCP_CTL(tcp_flags, tcp_offset);
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+        if (gre_tnl) {
Open vSwitch CI 70cc8f
+            struct gre_base_hdr *ghdr;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            ghdr = dp_packet_l4(seg);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            if (ghdr->flags & htons(GRE_CSUM)) {
Open vSwitch CI 70cc8f
+                ovs_be16 *csum_opt = (ovs_be16 *) (ghdr + 1);
Open vSwitch CI 70cc8f
+                *csum_opt = 0;
Open vSwitch CI 70cc8f
+                *csum_opt = csum(ghdr, dp_packet_l4_size(seg));
Open vSwitch CI 70cc8f
+            }
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
         if (dp_packet_batch_is_full(curr_batch)) {
Open vSwitch CI 70cc8f
             curr_batch++;
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
diff --git a/lib/dp-packet.c b/lib/dp-packet.c
Open vSwitch CI 70cc8f
index df7bf8e6b3..dad0d7be3a 100644
Open vSwitch CI 70cc8f
--- a/lib/dp-packet.c
Open vSwitch CI 70cc8f
+++ b/lib/dp-packet.c
Open vSwitch CI 70cc8f
@@ -604,6 +604,8 @@ dp_packet_ol_send_prepare(struct dp_packet *p, uint64_t flags)
Open vSwitch CI 70cc8f
                        NETDEV_TX_OFFLOAD_SCTP_CKSUM |
Open vSwitch CI 70cc8f
                        NETDEV_TX_OFFLOAD_IPV4_CKSUM);
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
+    } else if (dp_packet_hwol_is_tunnel_gre(p)) {
Open vSwitch CI 70cc8f
+        tnl_inner = true;
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     if (dp_packet_hwol_tx_ip_csum(p)) {
Open vSwitch CI 70cc8f
diff --git a/lib/dp-packet.h b/lib/dp-packet.h
Open vSwitch CI 70cc8f
index 4afbbe7223..f94a82b07c 100644
Open vSwitch CI 70cc8f
--- a/lib/dp-packet.h
Open vSwitch CI 70cc8f
+++ b/lib/dp-packet.h
Open vSwitch CI 70cc8f
@@ -104,6 +104,9 @@ enum dp_packet_offload_mask {
Open vSwitch CI 70cc8f
     /* Offload tunnel packet, outer header is IPv6. */
Open vSwitch CI 70cc8f
     DEF_OL_FLAG(DP_PACKET_OL_TX_OUTER_IPV6,
Open vSwitch CI 70cc8f
                 RTE_MBUF_F_TX_OUTER_IPV6, 0x40000),
Open vSwitch CI 70cc8f
+    /* Offload packet is GRE tunnel. */
Open vSwitch CI 70cc8f
+    DEF_OL_FLAG(DP_PACKET_OL_TX_TUNNEL_GRE,
Open vSwitch CI 70cc8f
+                RTE_MBUF_F_TX_TUNNEL_GRE, 0x80000),
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     /* Adding new field requires adding to DP_PACKET_OL_SUPPORTED_MASK. */
Open vSwitch CI 70cc8f
 };
Open vSwitch CI 70cc8f
@@ -123,6 +126,7 @@ enum dp_packet_offload_mask {
Open vSwitch CI 70cc8f
                                      DP_PACKET_OL_TX_IP_CKSUM        | \
Open vSwitch CI 70cc8f
                                      DP_PACKET_OL_TX_TUNNEL_GENEVE   | \
Open vSwitch CI 70cc8f
                                      DP_PACKET_OL_TX_TUNNEL_VXLAN    | \
Open vSwitch CI 70cc8f
+                                     DP_PACKET_OL_TX_TUNNEL_GRE      | \
Open vSwitch CI 70cc8f
                                      DP_PACKET_OL_TX_OUTER_IPV4      | \
Open vSwitch CI 70cc8f
                                      DP_PACKET_OL_TX_OUTER_IP_CKSUM  | \
Open vSwitch CI 70cc8f
                                      DP_PACKET_OL_TX_OUTER_UDP_CKSUM | \
Open vSwitch CI 70cc8f
@@ -1171,6 +1175,22 @@ dp_packet_hwol_is_tunnel_vxlan(struct dp_packet *b)
Open vSwitch CI 70cc8f
     return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_TUNNEL_VXLAN);
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+/* Returns 'true' if packet 'b' is marked for GRE tunnel offloading. */
Open vSwitch CI 70cc8f
+static inline bool
Open vSwitch CI 70cc8f
+dp_packet_hwol_is_tunnel_gre(struct dp_packet *b)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_TUNNEL_GRE);
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+/* Returns true if packet 'b' has any offloadable tunnel type. */
Open vSwitch CI 70cc8f
+static inline bool
Open vSwitch CI 70cc8f
+dp_packet_hwol_is_tunnel(struct dp_packet *b)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    return !!(*dp_packet_ol_flags_ptr(b) & (DP_PACKET_OL_TX_TUNNEL_VXLAN |
Open vSwitch CI 70cc8f
+                                            DP_PACKET_OL_TX_TUNNEL_GRE |
Open vSwitch CI 70cc8f
+                                            DP_PACKET_OL_TX_TUNNEL_GENEVE));
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 /* Returns 'true' if packet 'b' is marked for outer IPv4 checksum offload. */
Open vSwitch CI 70cc8f
 static inline bool
Open vSwitch CI 70cc8f
 dp_packet_hwol_is_outer_ipv4_cksum(const struct dp_packet *b)
Open vSwitch CI 70cc8f
@@ -1289,11 +1309,19 @@ dp_packet_hwol_set_tunnel_vxlan(struct dp_packet *b)
Open vSwitch CI 70cc8f
     *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TUNNEL_VXLAN;
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+/* Mark packet 'b' for GRE tunnel offloading. */
Open vSwitch CI 70cc8f
+static inline void
Open vSwitch CI 70cc8f
+dp_packet_hwol_set_tunnel_gre(struct dp_packet *b)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TUNNEL_GRE;
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 /* Clears tunnel offloading marks. */
Open vSwitch CI 70cc8f
 static inline void
Open vSwitch CI 70cc8f
 dp_packet_hwol_reset_tunnel(struct dp_packet *b)
Open vSwitch CI 70cc8f
 {
Open vSwitch CI 70cc8f
     *dp_packet_ol_flags_ptr(b) &= ~(DP_PACKET_OL_TX_TUNNEL_VXLAN |
Open vSwitch CI 70cc8f
+                                    DP_PACKET_OL_TX_TUNNEL_GRE |
Open vSwitch CI 70cc8f
                                     DP_PACKET_OL_TX_TUNNEL_GENEVE);
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
@@ -1352,6 +1380,9 @@ dp_packet_hwol_reset_tcp_seg(struct dp_packet *p)
Open vSwitch CI 70cc8f
             ol_flags |= DP_PACKET_OL_TX_OUTER_IP_CKSUM;
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
         ol_flags |= DP_PACKET_OL_TX_OUTER_UDP_CKSUM;
Open vSwitch CI 70cc8f
+    } else if (ol_flags & DP_PACKET_OL_TX_TUNNEL_GRE &&
Open vSwitch CI 70cc8f
+               ol_flags & DP_PACKET_OL_TX_OUTER_IPV4) {
Open vSwitch CI 70cc8f
+        ol_flags |= DP_PACKET_OL_TX_OUTER_IP_CKSUM;
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     *dp_packet_ol_flags_ptr(p) = ol_flags;
Open vSwitch CI 70cc8f
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
Open vSwitch CI 70cc8f
index 2a529f272d..b572fab23d 100644
Open vSwitch CI 70cc8f
--- a/lib/dpif-netdev.c
Open vSwitch CI 70cc8f
+++ b/lib/dpif-netdev.c
Open vSwitch CI 70cc8f
@@ -8928,9 +8928,7 @@ dp_netdev_recirculate(struct dp_netdev_pmd_thread *pmd,
Open vSwitch CI 70cc8f
     struct dp_packet *packet;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, packets) {
Open vSwitch CI 70cc8f
-        if (dp_packet_hwol_is_tunnel_geneve(packet) ||
Open vSwitch CI 70cc8f
-                dp_packet_hwol_is_tunnel_vxlan(packet)) {
Open vSwitch CI 70cc8f
-
Open vSwitch CI 70cc8f
+        if (dp_packet_hwol_is_tunnel(packet)) {
Open vSwitch CI 70cc8f
             if (dp_packet_hwol_is_tso(packet)) {
Open vSwitch CI 70cc8f
                 /* Can't perform GSO in the middle of a pipeline. */
Open vSwitch CI 70cc8f
                 COVERAGE_INC(datapath_drop_tunnel_tso_recirc);
Open vSwitch CI 70cc8f
diff --git a/lib/flow.c b/lib/flow.c
Open vSwitch CI 70cc8f
index 9be4375246..0eb34892f2 100644
Open vSwitch CI 70cc8f
--- a/lib/flow.c
Open vSwitch CI 70cc8f
+++ b/lib/flow.c
Open vSwitch CI 70cc8f
@@ -1187,7 +1187,7 @@ parse_dl_type(const void **datap, size_t *sizep, ovs_be16 *first_vlan_tci_p)
Open vSwitch CI 70cc8f
  * If 'packet' is not an Ethernet packet embedding TCP, returns 0.
Open vSwitch CI 70cc8f
  * 'dl_type_p' will be set only if the 'packet' is an Ethernet packet.
Open vSwitch CI 70cc8f
  * 'nw_frag_p' will be set only if the 'packet' is an IP packet.
Open vSwitch CI 70cc8f
- * 'first_vlan_tci' will be set only if the 'packet' contains vlan header.
Open vSwitch CI 70cc8f
+ * 'first_vlan_tci_p' will be set only if the 'packet' contains vlan header.
Open vSwitch CI 70cc8f
  *
Open vSwitch CI 70cc8f
  * The caller must ensure that 'packet' is at least ETH_HEADER_LEN bytes
Open vSwitch CI 70cc8f
  * long.'*/
Open vSwitch CI 70cc8f
diff --git a/lib/ipf.c b/lib/ipf.c
Open vSwitch CI 70cc8f
index 59e2323557..b76181e793 100644
Open vSwitch CI 70cc8f
--- a/lib/ipf.c
Open vSwitch CI 70cc8f
+++ b/lib/ipf.c
Open vSwitch CI 70cc8f
@@ -410,11 +410,12 @@ ipf_reassemble_v4_frags(struct ipf_list *ipf_list)
Open vSwitch CI 70cc8f
     dp_packet_set_size(pkt, dp_packet_size(pkt) - dp_packet_l2_pad_size(pkt));
Open vSwitch CI 70cc8f
     struct ip_header *l3 = dp_packet_l3(pkt);
Open vSwitch CI 70cc8f
     int len = ntohs(l3->ip_tot_len);
Open vSwitch CI 70cc8f
+    int orig_len = dp_packet_size(pkt);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     int rest_len = frag_list[ipf_list->last_inuse_idx].end_data_byte -
Open vSwitch CI 70cc8f
                    frag_list[1].start_data_byte + 1;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-    if (len + rest_len > IPV4_PACKET_MAX_SIZE) {
Open vSwitch CI 70cc8f
+    if (orig_len + rest_len > IPV4_PACKET_MAX_SIZE) {
Open vSwitch CI 70cc8f
         ipf_print_reass_packet(
Open vSwitch CI 70cc8f
             "Unsupported big reassembled v4 packet; v4 hdr:", l3);
Open vSwitch CI 70cc8f
         dp_packet_delete(pkt);
Open vSwitch CI 70cc8f
@@ -459,11 +460,12 @@ ipf_reassemble_v6_frags(struct ipf_list *ipf_list)
Open vSwitch CI 70cc8f
     dp_packet_set_size(pkt, dp_packet_size(pkt) - dp_packet_l2_pad_size(pkt));
Open vSwitch CI 70cc8f
     struct  ovs_16aligned_ip6_hdr *l3 = dp_packet_l3(pkt);
Open vSwitch CI 70cc8f
     int pl = ntohs(l3->ip6_plen) - sizeof(struct ovs_16aligned_ip6_frag);
Open vSwitch CI 70cc8f
+    int orig_len = dp_packet_size(pkt);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     int rest_len = frag_list[ipf_list->last_inuse_idx].end_data_byte -
Open vSwitch CI 70cc8f
                    frag_list[1].start_data_byte + 1;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-    if (pl + rest_len > IPV6_PACKET_MAX_DATA) {
Open vSwitch CI 70cc8f
+    if (orig_len + rest_len > IPV6_PACKET_MAX_DATA) {
Open vSwitch CI 70cc8f
         ipf_print_reass_packet(
Open vSwitch CI 70cc8f
              "Unsupported big reassembled v6 packet; v6 hdr:", l3);
Open vSwitch CI 70cc8f
         dp_packet_delete(pkt);
Open vSwitch CI 70cc8f
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
Open vSwitch CI 70cc8f
index b88247a2d0..549887b313 100644
Open vSwitch CI 70cc8f
--- a/lib/netdev-dpdk.c
Open vSwitch CI 70cc8f
+++ b/lib/netdev-dpdk.c
Open vSwitch CI 70cc8f
@@ -427,6 +427,7 @@ enum dpdk_hw_ol_features {
Open vSwitch CI 70cc8f
     NETDEV_TX_GENEVE_TNL_TSO_OFFLOAD = 1 << 9,
Open vSwitch CI 70cc8f
     NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD = 1 << 10,
Open vSwitch CI 70cc8f
     NETDEV_TX_OUTER_UDP_CKSUM_OFFLOAD = 1 << 11,
Open vSwitch CI 70cc8f
+    NETDEV_TX_GRE_TNL_TSO_OFFLOAD = 1 << 12,
Open vSwitch CI 70cc8f
 };
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 enum dpdk_rx_steer_flags {
Open vSwitch CI 70cc8f
@@ -1100,6 +1101,8 @@ netdev_dpdk_update_netdev_flags(struct netdev_dpdk *dev)
Open vSwitch CI 70cc8f
                                    NETDEV_TX_OFFLOAD_TCP_TSO);
Open vSwitch CI 70cc8f
     netdev_dpdk_update_netdev_flag(dev, NETDEV_TX_VXLAN_TNL_TSO_OFFLOAD,
Open vSwitch CI 70cc8f
                                    NETDEV_TX_VXLAN_TNL_TSO);
Open vSwitch CI 70cc8f
+    netdev_dpdk_update_netdev_flag(dev, NETDEV_TX_GRE_TNL_TSO_OFFLOAD,
Open vSwitch CI 70cc8f
+                                   NETDEV_TX_GRE_TNL_TSO);
Open vSwitch CI 70cc8f
     netdev_dpdk_update_netdev_flag(dev, NETDEV_TX_GENEVE_TNL_TSO_OFFLOAD,
Open vSwitch CI 70cc8f
                                    NETDEV_TX_GENEVE_TNL_TSO);
Open vSwitch CI 70cc8f
     netdev_dpdk_update_netdev_flag(dev, NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD,
Open vSwitch CI 70cc8f
@@ -1167,6 +1170,10 @@ dpdk_eth_dev_port_config(struct netdev_dpdk *dev,
Open vSwitch CI 70cc8f
         conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_GENEVE_TNL_TSO;
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+    if (dev->hw_ol_features & NETDEV_TX_GRE_TNL_TSO_OFFLOAD) {
Open vSwitch CI 70cc8f
+        conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO;
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
     if (dev->hw_ol_features & NETDEV_TX_OUTER_IP_CKSUM_OFFLOAD) {
Open vSwitch CI 70cc8f
         conf.txmode.offloads |= RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM;
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
@@ -1443,6 +1450,13 @@ dpdk_eth_dev_init(struct netdev_dpdk *dev)
Open vSwitch CI 70cc8f
             VLOG_WARN("%s: Tx Geneve tunnel TSO offload is not supported.",
Open vSwitch CI 70cc8f
                       netdev_get_name(&dev->up));
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+        if (info.tx_offload_capa & RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO) {
Open vSwitch CI 70cc8f
+            dev->hw_ol_features |= NETDEV_TX_GRE_TNL_TSO_OFFLOAD;
Open vSwitch CI 70cc8f
+        } else {
Open vSwitch CI 70cc8f
+            VLOG_WARN("%s: Tx GRE tunnel TSO offload is not supported.",
Open vSwitch CI 70cc8f
+                      netdev_get_name(&dev->up));
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     n_rxq = MIN(info.max_rx_queues, dev->up.n_rxq);
Open vSwitch CI 70cc8f
@@ -2650,6 +2664,7 @@ netdev_dpdk_prep_hwol_packet(struct netdev_dpdk *dev, struct rte_mbuf *mbuf)
Open vSwitch CI 70cc8f
     const uint64_t tunnel_type = mbuf->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK;
Open vSwitch CI 70cc8f
     if (OVS_UNLIKELY(tunnel_type &&
Open vSwitch CI 70cc8f
                      tunnel_type != RTE_MBUF_F_TX_TUNNEL_GENEVE &&
Open vSwitch CI 70cc8f
+                     tunnel_type != RTE_MBUF_F_TX_TUNNEL_GRE &&
Open vSwitch CI 70cc8f
                      tunnel_type != RTE_MBUF_F_TX_TUNNEL_VXLAN)) {
Open vSwitch CI 70cc8f
         VLOG_WARN_RL(&rl, "%s: Unexpected tunnel type: %#"PRIx64,
Open vSwitch CI 70cc8f
                      netdev_get_name(&dev->up), tunnel_type);
Open vSwitch CI 70cc8f
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
Open vSwitch CI 70cc8f
index ede5e16865..62e1a0c870 100644
Open vSwitch CI 70cc8f
--- a/lib/netdev-native-tnl.c
Open vSwitch CI 70cc8f
+++ b/lib/netdev-native-tnl.c
Open vSwitch CI 70cc8f
@@ -194,8 +194,7 @@ netdev_tnl_push_ip_header(struct dp_packet *packet, const void *header,
Open vSwitch CI 70cc8f
         packet_set_ipv6_flow_label(&ip6->ip6_flow, ipv6_label);
Open vSwitch CI 70cc8f
         packet->l4_ofs = dp_packet_size(packet) - *ip_tot_size;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-        if (dp_packet_hwol_is_tunnel_geneve(packet) ||
Open vSwitch CI 70cc8f
-            dp_packet_hwol_is_tunnel_vxlan(packet)) {
Open vSwitch CI 70cc8f
+        if (dp_packet_hwol_is_tunnel(packet)) {
Open vSwitch CI 70cc8f
             dp_packet_hwol_set_tx_outer_ipv6(packet);
Open vSwitch CI 70cc8f
         } else {
Open vSwitch CI 70cc8f
             dp_packet_hwol_set_tx_ipv6(packet);
Open vSwitch CI 70cc8f
@@ -207,8 +206,7 @@ netdev_tnl_push_ip_header(struct dp_packet *packet, const void *header,
Open vSwitch CI 70cc8f
         ip = netdev_tnl_ip_hdr(eth);
Open vSwitch CI 70cc8f
         ip->ip_tot_len = htons(*ip_tot_size);
Open vSwitch CI 70cc8f
         /* Postpone checksum to when the packet is pushed to the port. */
Open vSwitch CI 70cc8f
-        if (dp_packet_hwol_is_tunnel_geneve(packet) ||
Open vSwitch CI 70cc8f
-            dp_packet_hwol_is_tunnel_vxlan(packet)) {
Open vSwitch CI 70cc8f
+        if (dp_packet_hwol_is_tunnel(packet)) {
Open vSwitch CI 70cc8f
             dp_packet_hwol_set_tx_outer_ipv4(packet);
Open vSwitch CI 70cc8f
             dp_packet_hwol_set_tx_outer_ipv4_csum(packet);
Open vSwitch CI 70cc8f
         } else {
Open vSwitch CI 70cc8f
@@ -271,7 +269,9 @@ dp_packet_tnl_ol_process(struct dp_packet *packet,
Open vSwitch CI 70cc8f
         ip = dp_packet_l3(packet);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
         if (data->tnl_type == OVS_VPORT_TYPE_GENEVE ||
Open vSwitch CI 70cc8f
-            data->tnl_type == OVS_VPORT_TYPE_VXLAN) {
Open vSwitch CI 70cc8f
+            data->tnl_type == OVS_VPORT_TYPE_VXLAN ||
Open vSwitch CI 70cc8f
+            data->tnl_type == OVS_VPORT_TYPE_GRE ||
Open vSwitch CI 70cc8f
+            data->tnl_type == OVS_VPORT_TYPE_IP6GRE) {
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
             if (IP_VER(ip->ip_ihl_ver) == 4) {
Open vSwitch CI 70cc8f
                 dp_packet_hwol_set_tx_ipv4(packet);
Open vSwitch CI 70cc8f
@@ -286,6 +286,9 @@ dp_packet_tnl_ol_process(struct dp_packet *packet,
Open vSwitch CI 70cc8f
         dp_packet_hwol_set_tunnel_geneve(packet);
Open vSwitch CI 70cc8f
     } else if (data->tnl_type == OVS_VPORT_TYPE_VXLAN) {
Open vSwitch CI 70cc8f
         dp_packet_hwol_set_tunnel_vxlan(packet);
Open vSwitch CI 70cc8f
+    } else if (data->tnl_type == OVS_VPORT_TYPE_GRE ||
Open vSwitch CI 70cc8f
+               data->tnl_type == OVS_VPORT_TYPE_IP6GRE) {
Open vSwitch CI 70cc8f
+        dp_packet_hwol_set_tunnel_gre(packet);
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
@@ -535,9 +538,13 @@ netdev_gre_push_header(const struct netdev *netdev,
Open vSwitch CI 70cc8f
                        const struct ovs_action_push_tnl *data)
Open vSwitch CI 70cc8f
 {
Open vSwitch CI 70cc8f
     struct netdev_vport *dev = netdev_vport_cast(netdev);
Open vSwitch CI 70cc8f
+    uint16_t l3_ofs = packet->l3_ofs;
Open vSwitch CI 70cc8f
+    uint16_t l4_ofs = packet->l4_ofs;
Open vSwitch CI 70cc8f
     struct gre_base_hdr *greh;
Open vSwitch CI 70cc8f
     int ip_tot_size;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+    dp_packet_tnl_ol_process(packet, data);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
     greh = netdev_tnl_push_ip_header(packet, data->header, data->header_len,
Open vSwitch CI 70cc8f
                                      &ip_tot_size, 0);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
@@ -547,11 +554,24 @@ netdev_gre_push_header(const struct netdev *netdev,
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     if (greh->flags & htons(GRE_SEQ)) {
Open vSwitch CI 70cc8f
-        /* Last 4 byte is GRE seqno */
Open vSwitch CI 70cc8f
-        int seq_ofs = gre_header_len(greh->flags) - 4;
Open vSwitch CI 70cc8f
-        ovs_16aligned_be32 *seq_opt =
Open vSwitch CI 70cc8f
-            ALIGNED_CAST(ovs_16aligned_be32 *, (char *)greh + seq_ofs);
Open vSwitch CI 70cc8f
-        put_16aligned_be32(seq_opt, htonl(atomic_count_inc(&dev->gre_seqno)));
Open vSwitch CI 70cc8f
+        if (!dp_packet_hwol_is_tso(packet)) {
Open vSwitch CI 70cc8f
+            /* Last 4 bytes are GRE seqno. */
Open vSwitch CI 70cc8f
+            int seq_ofs = gre_header_len(greh->flags) - 4;
Open vSwitch CI 70cc8f
+            ovs_16aligned_be32 *seq_opt =
Open vSwitch CI 70cc8f
+                ALIGNED_CAST(ovs_16aligned_be32 *, (char *) greh + seq_ofs);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            put_16aligned_be32(seq_opt,
Open vSwitch CI 70cc8f
+                               htonl(atomic_count_inc(&dev->gre_seqno)));
Open vSwitch CI 70cc8f
+        } else {
Open vSwitch CI 70cc8f
+            VLOG_WARN_RL(&err_rl, "Cannot use GRE Sequence numbers with TSO.");
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    if (l3_ofs != UINT16_MAX) {
Open vSwitch CI 70cc8f
+        packet->inner_l3_ofs = l3_ofs + data->header_len;
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
+    if (l4_ofs != UINT16_MAX) {
Open vSwitch CI 70cc8f
+        packet->inner_l4_ofs = l4_ofs + data->header_len;
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI ee4d11
diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c
Open vSwitch CI ee4d11
index 9e163c2a63..38ea95bd49 100644
Open vSwitch CI ee4d11
--- a/lib/netdev-offload-tc.c
Open vSwitch CI ee4d11
+++ b/lib/netdev-offload-tc.c
Open vSwitch CI ee4d11
@@ -2293,6 +2293,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
Open vSwitch CI ee4d11
     const struct flow_tnl *tnl = &match->flow.tunnel;
Open vSwitch CI ee4d11
     struct flow_tnl *tnl_mask = &mask->tunnel;
Open vSwitch CI ee4d11
     struct dpif_flow_stats adjust_stats;
Open vSwitch CI ee4d11
+    bool exact_match_on_dl_type;
Open vSwitch CI ee4d11
     bool recirc_act = false;
Open vSwitch CI ee4d11
     uint32_t block_id = 0;
Open vSwitch CI ee4d11
     struct tcf_id id;
Open vSwitch CI ee4d11
@@ -2310,6 +2311,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
Open vSwitch CI ee4d11
 
Open vSwitch CI ee4d11
     memset(&flower, 0, sizeof flower);
Open vSwitch CI ee4d11
 
Open vSwitch CI ee4d11
+    exact_match_on_dl_type = mask->dl_type == htons(0xffff);
Open vSwitch CI ee4d11
     chain = key->recirc_id;
Open vSwitch CI ee4d11
     mask->recirc_id = 0;
Open vSwitch CI ee4d11
 
Open vSwitch CI ee4d11
@@ -2503,7 +2505,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
Open vSwitch CI ee4d11
     mask->dl_type = 0;
Open vSwitch CI ee4d11
     mask->in_port.odp_port = 0;
Open vSwitch CI ee4d11
 
Open vSwitch CI ee4d11
-    if (key->dl_type == htons(ETH_P_ARP)) {
Open vSwitch CI ee4d11
+    if (exact_match_on_dl_type && key->dl_type == htons(ETH_P_ARP)) {
Open vSwitch CI ee4d11
             flower.key.arp.spa = key->nw_src;
Open vSwitch CI ee4d11
             flower.key.arp.tpa = key->nw_dst;
Open vSwitch CI ee4d11
             flower.key.arp.sha = key->arp_sha;
Open vSwitch CI ee4d11
@@ -2522,7 +2524,8 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
Open vSwitch CI ee4d11
             memset(&mask->arp_tha, 0, sizeof mask->arp_tha);
Open vSwitch CI ee4d11
     }
Open vSwitch CI ee4d11
 
Open vSwitch CI ee4d11
-    if (is_ip_any(key) && !is_ipv6_fragment_and_masked(key, mask)) {
Open vSwitch CI ee4d11
+    if (exact_match_on_dl_type && is_ip_any(key)
Open vSwitch CI ee4d11
+        && !is_ipv6_fragment_and_masked(key, mask)) {
Open vSwitch CI ee4d11
         flower.key.ip_proto = key->nw_proto;
Open vSwitch CI ee4d11
         flower.mask.ip_proto = mask->nw_proto;
Open vSwitch CI ee4d11
         mask->nw_proto = 0;
Open vSwitch CI ee4d11
@@ -2552,9 +2555,9 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match,
Open vSwitch CI ee4d11
         } else {
Open vSwitch CI ee4d11
             /* This scenario should not occur.  Currently, all installed IP DP
Open vSwitch CI ee4d11
              * flows perform a fully masked match on the fragmentation bits.
Open vSwitch CI ee4d11
-             * However, since TC depends on this behavior, we return ENOTSUPP
Open vSwitch CI ee4d11
+             * However, since TC depends on this behavior, we return EOPNOTSUPP
Open vSwitch CI ee4d11
              * for now in case this behavior changes in the future. */
Open vSwitch CI ee4d11
-             return EOPNOTSUPP;
Open vSwitch CI ee4d11
+            return EOPNOTSUPP;
Open vSwitch CI ee4d11
         }
Open vSwitch CI ee4d11
 
Open vSwitch CI ee4d11
         if (key->nw_proto == IPPROTO_TCP) {
Open vSwitch CI 70cc8f
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
Open vSwitch CI 70cc8f
index 22840a058b..5ae3794699 100644
Open vSwitch CI 70cc8f
--- a/lib/netdev-provider.h
Open vSwitch CI 70cc8f
+++ b/lib/netdev-provider.h
Open vSwitch CI 70cc8f
@@ -47,6 +47,7 @@ enum netdev_ol_flags {
Open vSwitch CI 70cc8f
     NETDEV_TX_GENEVE_TNL_TSO = 1 << 6,
Open vSwitch CI 70cc8f
     NETDEV_TX_OFFLOAD_OUTER_IP_CKSUM = 1 << 7,
Open vSwitch CI 70cc8f
     NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM = 1 << 8,
Open vSwitch CI 70cc8f
+    NETDEV_TX_GRE_TNL_TSO = 1 << 9,
Open vSwitch CI 70cc8f
 };
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 /* A network device (e.g. an Ethernet device).
Open vSwitch CI 1a3c29
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
Open vSwitch CI 1a3c29
index 2b2acd341d..46a62dbfc1 100644
Open vSwitch CI 1a3c29
--- a/lib/netdev-vport.c
Open vSwitch CI 1a3c29
+++ b/lib/netdev-vport.c
Open vSwitch CI 1a3c29
@@ -842,7 +842,8 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
Open vSwitch CI 1a3c29
             }
Open vSwitch CI 1a3c29
         } else if (!strcmp(node->key, "remote_cert") ||
Open vSwitch CI 1a3c29
                    !strcmp(node->key, "remote_name") ||
Open vSwitch CI 1a3c29
-                   !strcmp(node->key, "psk")) {
Open vSwitch CI 1a3c29
+                   !strcmp(node->key, "psk") ||
Open vSwitch CI 1a3c29
+                   !strncmp(node->key, "ipsec_", strlen("ipsec_"))) {
Open vSwitch CI 1a3c29
             /* When configuring OVS for IPsec, these keys may be set in the
Open vSwitch CI 1a3c29
                tunnel port's 'options' column. 'ovs-vswitchd' does not directly
Open vSwitch CI 1a3c29
                use them, but they are read by 'ovs-monitor-ipsec'. In order to
Open vSwitch CI 70cc8f
diff --git a/lib/netdev.c b/lib/netdev.c
Open vSwitch CI 70cc8f
index 02beac9d0b..9dd94ebdd7 100644
Open vSwitch CI 70cc8f
--- a/lib/netdev.c
Open vSwitch CI 70cc8f
+++ b/lib/netdev.c
Open vSwitch CI 70cc8f
@@ -916,11 +916,11 @@ netdev_send(struct netdev *netdev, int qid, struct dp_packet_batch *batch,
Open vSwitch CI 70cc8f
                 }
Open vSwitch CI 70cc8f
             }
Open vSwitch CI 70cc8f
         } else if (!(netdev_flags & (NETDEV_TX_VXLAN_TNL_TSO |
Open vSwitch CI 70cc8f
+                                     NETDEV_TX_GRE_TNL_TSO |
Open vSwitch CI 70cc8f
                                      NETDEV_TX_GENEVE_TNL_TSO))) {
Open vSwitch CI 70cc8f
             DP_PACKET_BATCH_FOR_EACH (i, packet, batch) {
Open vSwitch CI 70cc8f
                 if (dp_packet_hwol_is_tso(packet) &&
Open vSwitch CI 70cc8f
-                    (dp_packet_hwol_is_tunnel_vxlan(packet) ||
Open vSwitch CI 70cc8f
-                     dp_packet_hwol_is_tunnel_geneve(packet))) {
Open vSwitch CI 70cc8f
+                    dp_packet_hwol_is_tunnel(packet)) {
Open vSwitch CI 70cc8f
                     return netdev_send_tso(netdev, qid, batch, concurrent_txq);
Open vSwitch CI 70cc8f
                 }
Open vSwitch CI 70cc8f
             }
Open vSwitch CI 70cc8f
@@ -1011,6 +1011,8 @@ netdev_push_header(const struct netdev *netdev,
Open vSwitch CI 70cc8f
     DP_PACKET_BATCH_REFILL_FOR_EACH (i, size, packet, batch) {
Open vSwitch CI 70cc8f
         if (OVS_UNLIKELY(data->tnl_type != OVS_VPORT_TYPE_GENEVE &&
Open vSwitch CI 70cc8f
                          data->tnl_type != OVS_VPORT_TYPE_VXLAN &&
Open vSwitch CI 70cc8f
+                         data->tnl_type != OVS_VPORT_TYPE_GRE &&
Open vSwitch CI 70cc8f
+                         data->tnl_type != OVS_VPORT_TYPE_IP6GRE &&
Open vSwitch CI 70cc8f
                          dp_packet_hwol_is_tso(packet))) {
Open vSwitch CI 70cc8f
             COVERAGE_INC(netdev_push_header_drops);
Open vSwitch CI 70cc8f
             dp_packet_delete(packet);
Open vSwitch CI 70cc8f
@@ -1019,16 +1021,17 @@ netdev_push_header(const struct netdev *netdev,
Open vSwitch CI 70cc8f
                          netdev_get_name(netdev), netdev_get_type(netdev));
Open vSwitch CI 70cc8f
         } else {
Open vSwitch CI 70cc8f
             if (data->tnl_type != OVS_VPORT_TYPE_GENEVE &&
Open vSwitch CI 70cc8f
-                data->tnl_type != OVS_VPORT_TYPE_VXLAN) {
Open vSwitch CI 70cc8f
+                data->tnl_type != OVS_VPORT_TYPE_VXLAN &&
Open vSwitch CI 70cc8f
+                data->tnl_type != OVS_VPORT_TYPE_GRE &&
Open vSwitch CI 70cc8f
+                data->tnl_type != OVS_VPORT_TYPE_IP6GRE) {
Open vSwitch CI 70cc8f
                 dp_packet_ol_send_prepare(packet, 0);
Open vSwitch CI 70cc8f
-            } else if (dp_packet_hwol_is_tunnel_geneve(packet) ||
Open vSwitch CI 70cc8f
-                       dp_packet_hwol_is_tunnel_vxlan(packet)) {
Open vSwitch CI 70cc8f
+            } else if (dp_packet_hwol_is_tunnel(packet)) {
Open vSwitch CI 70cc8f
                 if (dp_packet_hwol_is_tso(packet)) {
Open vSwitch CI 70cc8f
                     COVERAGE_INC(netdev_push_header_drops);
Open vSwitch CI 70cc8f
                     dp_packet_delete(packet);
Open vSwitch CI 70cc8f
                     VLOG_WARN_RL(&rl, "%s: Tunneling packets with TSO is not "
Open vSwitch CI 70cc8f
                                       "supported with multiple levels of "
Open vSwitch CI 70cc8f
-                                      "VXLAN or GENEVE encapsulation.",
Open vSwitch CI 70cc8f
+                                      "VXLAN, GENEVE, or GRE encapsulation.",
Open vSwitch CI 70cc8f
                                  netdev_get_name(netdev));
Open vSwitch CI 70cc8f
                     continue;
Open vSwitch CI 70cc8f
                 }
Open vSwitch CI 70cc8f
@@ -1480,6 +1483,7 @@ netdev_get_status(const struct netdev *netdev, struct smap *smap)
Open vSwitch CI 70cc8f
         OL_ADD_STAT("sctp_csum", NETDEV_TX_OFFLOAD_SCTP_CKSUM);
Open vSwitch CI 70cc8f
         OL_ADD_STAT("tcp_seg", NETDEV_TX_OFFLOAD_TCP_TSO);
Open vSwitch CI 70cc8f
         OL_ADD_STAT("vxlan_tso", NETDEV_TX_VXLAN_TNL_TSO);
Open vSwitch CI 70cc8f
+        OL_ADD_STAT("gre_tso", NETDEV_TX_GRE_TNL_TSO);
Open vSwitch CI 70cc8f
         OL_ADD_STAT("geneve_tso", NETDEV_TX_GENEVE_TNL_TSO);
Open vSwitch CI 70cc8f
         OL_ADD_STAT("out_ip_csum", NETDEV_TX_OFFLOAD_OUTER_IP_CKSUM);
Open vSwitch CI 70cc8f
         OL_ADD_STAT("out_udp_csum", NETDEV_TX_OFFLOAD_OUTER_UDP_CKSUM);
Open vSwitch CI 70cc8f
diff --git a/lib/netlink.c b/lib/netlink.c
Open vSwitch CI 70cc8f
index 1e8d5a8ec5..446a0679ed 100644
Open vSwitch CI 70cc8f
--- a/lib/netlink.c
Open vSwitch CI 70cc8f
+++ b/lib/netlink.c
Open vSwitch CI 70cc8f
@@ -29,6 +29,16 @@
Open vSwitch CI 70cc8f
 #include "openvswitch/vlog.h"
Open vSwitch CI 70cc8f
 #include "util.h"
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+#ifdef HAVE_NETLINK
Open vSwitch CI 70cc8f
+#include <linux/rtnetlink.h>
Open vSwitch CI 70cc8f
+#else
Open vSwitch CI 70cc8f
+/* RTA_VIA */
Open vSwitch CI 70cc8f
+struct rtvia {
Open vSwitch CI 70cc8f
+    sa_family_t    rtvia_family;
Open vSwitch CI 70cc8f
+    uint8_t        rtvia_addr[];
Open vSwitch CI 70cc8f
+};
Open vSwitch CI 70cc8f
+#endif
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 VLOG_DEFINE_THIS_MODULE(netlink);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 /* A single (bad) Netlink message can in theory dump out many, many log
Open vSwitch CI 70cc8f
@@ -819,6 +829,7 @@ min_attr_len(enum nl_attr_type type)
Open vSwitch CI 70cc8f
     case NL_A_IPV6: return 16;
Open vSwitch CI 70cc8f
     case NL_A_NESTED: return 0;
Open vSwitch CI 70cc8f
     case NL_A_LL_ADDR: return 6; /* ETH_ALEN */
Open vSwitch CI 70cc8f
+    case NL_A_RTA_VIA: return sizeof(struct rtvia) + sizeof(struct in_addr);
Open vSwitch CI 70cc8f
     case N_NL_ATTR_TYPES: default: OVS_NOT_REACHED();
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
@@ -840,6 +851,7 @@ max_attr_len(enum nl_attr_type type)
Open vSwitch CI 70cc8f
     case NL_A_IPV6: return 16;
Open vSwitch CI 70cc8f
     case NL_A_NESTED: return SIZE_MAX;
Open vSwitch CI 70cc8f
     case NL_A_LL_ADDR: return 20; /* INFINIBAND_ALEN */
Open vSwitch CI 70cc8f
+    case NL_A_RTA_VIA: return sizeof(struct rtvia) + sizeof(struct in6_addr);
Open vSwitch CI 70cc8f
     case N_NL_ATTR_TYPES: default: OVS_NOT_REACHED();
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
diff --git a/lib/netlink.h b/lib/netlink.h
Open vSwitch CI 70cc8f
index 008604aa60..d98ef3a989 100644
Open vSwitch CI 70cc8f
--- a/lib/netlink.h
Open vSwitch CI 70cc8f
+++ b/lib/netlink.h
Open vSwitch CI 70cc8f
@@ -152,6 +152,7 @@ enum nl_attr_type
Open vSwitch CI 70cc8f
     NL_A_IPV6,
Open vSwitch CI 70cc8f
     NL_A_NESTED,
Open vSwitch CI 70cc8f
     NL_A_LL_ADDR,
Open vSwitch CI 70cc8f
+    NL_A_RTA_VIA,
Open vSwitch CI 70cc8f
     N_NL_ATTR_TYPES
Open vSwitch CI 70cc8f
 };
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
diff --git a/lib/route-table.c b/lib/route-table.c
Open vSwitch CI 56d821
index c6cb21394a..2bbb51c08f 100644
Open vSwitch CI 70cc8f
--- a/lib/route-table.c
Open vSwitch CI 70cc8f
+++ b/lib/route-table.c
Open vSwitch CI 70cc8f
@@ -32,6 +32,7 @@
Open vSwitch CI 70cc8f
 #include "netlink.h"
Open vSwitch CI 70cc8f
 #include "netlink-notifier.h"
Open vSwitch CI 70cc8f
 #include "netlink-socket.h"
Open vSwitch CI 70cc8f
+#include "openvswitch/list.h"
Open vSwitch CI 70cc8f
 #include "openvswitch/ofpbuf.h"
Open vSwitch CI 70cc8f
 #include "ovs-router.h"
Open vSwitch CI 70cc8f
 #include "packets.h"
Open vSwitch CI 70cc8f
@@ -47,27 +48,6 @@ VLOG_DEFINE_THIS_MODULE(route_table);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 COVERAGE_DEFINE(route_table_dump);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-struct route_data {
Open vSwitch CI 70cc8f
-    /* Copied from struct rtmsg. */
Open vSwitch CI 70cc8f
-    unsigned char rtm_dst_len;
Open vSwitch CI 70cc8f
-    bool local;
Open vSwitch CI 70cc8f
-
Open vSwitch CI 70cc8f
-    /* Extracted from Netlink attributes. */
Open vSwitch CI 70cc8f
-    struct in6_addr rta_dst; /* 0 if missing. */
Open vSwitch CI 70cc8f
-    struct in6_addr rta_prefsrc; /* 0 if missing. */
Open vSwitch CI 70cc8f
-    struct in6_addr rta_gw;
Open vSwitch CI 70cc8f
-    char ifname[IFNAMSIZ]; /* Interface name. */
Open vSwitch CI 70cc8f
-    uint32_t mark;
Open vSwitch CI 70cc8f
-};
Open vSwitch CI 70cc8f
-
Open vSwitch CI 70cc8f
-/* A digested version of a route message sent down by the kernel to indicate
Open vSwitch CI 70cc8f
- * that a route has changed. */
Open vSwitch CI 70cc8f
-struct route_table_msg {
Open vSwitch CI 70cc8f
-    bool relevant;        /* Should this message be processed? */
Open vSwitch CI 70cc8f
-    int nlmsg_type;       /* e.g. RTM_NEWROUTE, RTM_DELROUTE. */
Open vSwitch CI 70cc8f
-    struct route_data rd; /* Data parsed from this message. */
Open vSwitch CI 70cc8f
-};
Open vSwitch CI 70cc8f
-
Open vSwitch CI 70cc8f
 static struct ovs_mutex route_table_mutex = OVS_MUTEX_INITIALIZER;
Open vSwitch CI 70cc8f
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
@@ -76,7 +56,7 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
Open vSwitch CI 70cc8f
 static uint64_t rt_change_seq;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 static struct nln *nln = NULL;
Open vSwitch CI 70cc8f
-static struct route_table_msg rtmsg;
Open vSwitch CI 70cc8f
+static struct route_table_msg nln_rtmsg_change;
Open vSwitch CI 70cc8f
 static struct nln_notifier *route_notifier = NULL;
Open vSwitch CI 70cc8f
 static struct nln_notifier *route6_notifier = NULL;
Open vSwitch CI 70cc8f
 static struct nln_notifier *name_notifier = NULL;
Open vSwitch CI 70cc8f
@@ -84,14 +64,31 @@ static struct nln_notifier *name_notifier = NULL;
Open vSwitch CI 70cc8f
 static bool route_table_valid = false;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 static void route_table_reset(void);
Open vSwitch CI 70cc8f
-static void route_table_handle_msg(const struct route_table_msg *);
Open vSwitch CI 70cc8f
-static int route_table_parse(struct ofpbuf *, void *change);
Open vSwitch CI 70cc8f
-static void route_table_change(const struct route_table_msg *, void *);
Open vSwitch CI 70cc8f
+static void route_table_handle_msg(const struct route_table_msg *, void *aux);
Open vSwitch CI 70cc8f
+static void route_table_change(struct route_table_msg *, void *aux);
Open vSwitch CI 70cc8f
 static void route_map_clear(void);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 static void name_table_init(void);
Open vSwitch CI 70cc8f
 static void name_table_change(const struct rtnetlink_change *, void *);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+static void
Open vSwitch CI 70cc8f
+route_data_destroy_nexthops__(struct route_data *rd)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    struct route_data_nexthop *rdnh;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    LIST_FOR_EACH_POP (rdnh, nexthop_node, &rd->nexthops) {
Open vSwitch CI 70cc8f
+        if (rdnh && rdnh != &rd->primary_next_hop__) {
Open vSwitch CI 70cc8f
+            free(rdnh);
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+void
Open vSwitch CI 70cc8f
+route_data_destroy(struct route_data *rd)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    route_data_destroy_nexthops__(rd);
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 uint64_t
Open vSwitch CI 70cc8f
 route_table_get_change_seq(void)
Open vSwitch CI 70cc8f
 {
Open vSwitch CI 70cc8f
@@ -110,7 +107,7 @@ route_table_init(void)
Open vSwitch CI 70cc8f
     ovs_assert(!route6_notifier);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     ovs_router_init();
Open vSwitch CI 70cc8f
-    nln = nln_create(NETLINK_ROUTE, route_table_parse, &rtmsg);
Open vSwitch CI 70cc8f
+    nln = nln_create(NETLINK_ROUTE, route_table_parse, &nln_rtmsg_change);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     route_notifier =
Open vSwitch CI 70cc8f
         nln_notifier_create(nln, RTNLGRP_IPV4_ROUTE,
Open vSwitch CI 70cc8f
@@ -155,8 +152,10 @@ route_table_wait(void)
Open vSwitch CI 70cc8f
     ovs_mutex_unlock(&route_table_mutex);
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-static bool
Open vSwitch CI 70cc8f
-route_table_dump_one_table(unsigned char id)
Open vSwitch CI 70cc8f
+bool
Open vSwitch CI 70cc8f
+route_table_dump_one_table(uint32_t id,
Open vSwitch CI 70cc8f
+                           route_table_handle_msg_callback *handle_msg_cb,
Open vSwitch CI 70cc8f
+                           void *aux)
Open vSwitch CI 70cc8f
 {
Open vSwitch CI 70cc8f
     uint64_t reply_stub[NL_DUMP_BUFSIZE / 8];
Open vSwitch CI 70cc8f
     struct ofpbuf request, reply, buf;
Open vSwitch CI 70cc8f
@@ -170,7 +169,13 @@ route_table_dump_one_table(unsigned char id)
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     rq_msg = ofpbuf_put_zeros(&request, sizeof *rq_msg);
Open vSwitch CI 70cc8f
     rq_msg->rtm_family = AF_UNSPEC;
Open vSwitch CI 70cc8f
-    rq_msg->rtm_table = id;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    if (id > UCHAR_MAX) {
Open vSwitch CI 70cc8f
+        rq_msg->rtm_table = RT_TABLE_UNSPEC;
Open vSwitch CI 70cc8f
+        nl_msg_put_u32(&request, RTA_TABLE, id);
Open vSwitch CI 70cc8f
+    } else {
Open vSwitch CI 70cc8f
+        rq_msg->rtm_table = id;
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     nl_dump_start(&dump, NETLINK_ROUTE, &request);
Open vSwitch CI 70cc8f
     ofpbuf_uninit(&request);
Open vSwitch CI 70cc8f
@@ -186,7 +191,8 @@ route_table_dump_one_table(unsigned char id)
Open vSwitch CI 70cc8f
             if (!(nlmsghdr->nlmsg_flags & NLM_F_DUMP_FILTERED)) {
Open vSwitch CI 70cc8f
                 filtered = false;
Open vSwitch CI 70cc8f
             }
Open vSwitch CI 70cc8f
-            route_table_handle_msg(&msg;;
Open vSwitch CI 70cc8f
+            handle_msg_cb(&msg, aux);
Open vSwitch CI 70cc8f
+            route_data_destroy(&msg.rd);
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
     ofpbuf_uninit(&buf;;
Open vSwitch CI 70cc8f
@@ -198,7 +204,7 @@ route_table_dump_one_table(unsigned char id)
Open vSwitch CI 70cc8f
 static void
Open vSwitch CI 70cc8f
 route_table_reset(void)
Open vSwitch CI 70cc8f
 {
Open vSwitch CI 70cc8f
-    unsigned char tables[] = {
Open vSwitch CI 70cc8f
+    uint32_t tables[] = {
Open vSwitch CI 70cc8f
         RT_TABLE_DEFAULT,
Open vSwitch CI 70cc8f
         RT_TABLE_MAIN,
Open vSwitch CI 70cc8f
         RT_TABLE_LOCAL,
Open vSwitch CI 56d821
@@ -212,19 +218,39 @@ route_table_reset(void)
Open vSwitch CI 70cc8f
     COVERAGE_INC(route_table_dump);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     for (size_t i = 0; i < ARRAY_SIZE(tables); i++) {
Open vSwitch CI 70cc8f
-        if (!route_table_dump_one_table(tables[i])) {
Open vSwitch CI 70cc8f
+        if (!route_table_dump_one_table(tables[i],
Open vSwitch CI 70cc8f
+                                        route_table_handle_msg, NULL)) {
Open vSwitch CI 70cc8f
             /* Got unfiltered reply, no need to dump further. */
Open vSwitch CI 70cc8f
             break;
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-/* Return RTNLGRP_IPV4_ROUTE or RTNLGRP_IPV6_ROUTE on success, 0 on parse
Open vSwitch CI 70cc8f
- * error. */
Open vSwitch CI 56d821
+/* Returns true if the given route requires nexthop information (output
Open vSwitch CI 56d821
+ * interface, nexthop IP, ...).  Returns false for special route types
Open vSwitch CI 56d821
+ * that don't need this information. */
Open vSwitch CI 56d821
+static bool
Open vSwitch CI 56d821
+route_type_needs_nexthop(unsigned char rtmsg_type)
Open vSwitch CI 56d821
+{
Open vSwitch CI 56d821
+    switch (rtmsg_type) {
Open vSwitch CI 56d821
+    case RTN_BLACKHOLE:
Open vSwitch CI 56d821
+    case RTN_THROW:
Open vSwitch CI 56d821
+    case RTN_UNREACHABLE:
Open vSwitch CI 56d821
+    case RTN_PROHIBIT:
Open vSwitch CI 56d821
+        return false;
Open vSwitch CI 56d821
+
Open vSwitch CI 56d821
+    default:
Open vSwitch CI 56d821
+        return true;
Open vSwitch CI 56d821
+    }
Open vSwitch CI 56d821
+}
Open vSwitch CI 56d821
+
Open vSwitch CI 70cc8f
 static int
Open vSwitch CI 70cc8f
-route_table_parse(struct ofpbuf *buf, void *change_)
Open vSwitch CI 70cc8f
+route_table_parse__(struct ofpbuf *buf, size_t ofs,
Open vSwitch CI 70cc8f
+                    const struct nlmsghdr *nlmsg,
Open vSwitch CI 70cc8f
+                    const struct rtmsg *rtm,
Open vSwitch CI 70cc8f
+                    const struct rtnexthop *rtnh,
Open vSwitch CI 70cc8f
+                    struct route_table_msg *change)
Open vSwitch CI 70cc8f
 {
Open vSwitch CI 70cc8f
-    struct route_table_msg *change = change_;
Open vSwitch CI 70cc8f
     bool parsed, ipv4 = false;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     static const struct nl_policy policy[] = {
Open vSwitch CI 56d821
@@ -234,6 +260,9 @@ route_table_parse(struct ofpbuf *buf, void *change_)
Open vSwitch CI 70cc8f
         [RTA_MARK] = { .type = NL_A_U32, .optional = true },
Open vSwitch CI 70cc8f
         [RTA_PREFSRC] = { .type = NL_A_U32, .optional = true },
Open vSwitch CI 70cc8f
         [RTA_TABLE] = { .type = NL_A_U32, .optional = true },
Open vSwitch CI 70cc8f
+        [RTA_PRIORITY] = { .type = NL_A_U32, .optional = true },
Open vSwitch CI 70cc8f
+        [RTA_VIA] = { .type = NL_A_RTA_VIA, .optional = true },
Open vSwitch CI 70cc8f
+        [RTA_MULTIPATH] = { .type = NL_A_NESTED, .optional = true },
Open vSwitch CI 70cc8f
     };
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     static const struct nl_policy policy6[] = {
Open vSwitch CI 56d821
@@ -243,33 +272,36 @@ route_table_parse(struct ofpbuf *buf, void *change_)
Open vSwitch CI 70cc8f
         [RTA_GATEWAY] = { .type = NL_A_IPV6, .optional = true },
Open vSwitch CI 70cc8f
         [RTA_PREFSRC] = { .type = NL_A_IPV6, .optional = true },
Open vSwitch CI 70cc8f
         [RTA_TABLE] = { .type = NL_A_U32, .optional = true },
Open vSwitch CI 70cc8f
+        [RTA_PRIORITY] = { .type = NL_A_U32, .optional = true },
Open vSwitch CI 70cc8f
+        [RTA_VIA] = { .type = NL_A_RTA_VIA, .optional = true },
Open vSwitch CI 70cc8f
+        [RTA_MULTIPATH] = { .type = NL_A_NESTED, .optional = true },
Open vSwitch CI 70cc8f
     };
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     struct nlattr *attrs[ARRAY_SIZE(policy)];
Open vSwitch CI 70cc8f
-    const struct rtmsg *rtm;
Open vSwitch CI 70cc8f
-
Open vSwitch CI 70cc8f
-    rtm = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *rtm);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     if (rtm->rtm_family == AF_INET) {
Open vSwitch CI 70cc8f
-        parsed = nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct rtmsg),
Open vSwitch CI 70cc8f
-                                 policy, attrs, ARRAY_SIZE(policy));
Open vSwitch CI 70cc8f
+        parsed = nl_policy_parse(buf, ofs, policy, attrs,
Open vSwitch CI 70cc8f
+                                 ARRAY_SIZE(policy));
Open vSwitch CI 70cc8f
         ipv4 = true;
Open vSwitch CI 70cc8f
     } else if (rtm->rtm_family == AF_INET6) {
Open vSwitch CI 70cc8f
-        parsed = nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct rtmsg),
Open vSwitch CI 70cc8f
-                                 policy6, attrs, ARRAY_SIZE(policy6));
Open vSwitch CI 70cc8f
+        parsed = nl_policy_parse(buf, ofs, policy6, attrs,
Open vSwitch CI 70cc8f
+                                 ARRAY_SIZE(policy6));
Open vSwitch CI 70cc8f
     } else {
Open vSwitch CI 70cc8f
         VLOG_DBG_RL(&rl, "received non AF_INET rtnetlink route message");
Open vSwitch CI 70cc8f
         return 0;
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     if (parsed) {
Open vSwitch CI 70cc8f
-        const struct nlmsghdr *nlmsg;
Open vSwitch CI 70cc8f
-        uint32_t table_id;
Open vSwitch CI 70cc8f
+        struct route_data_nexthop *rdnh = NULL;
Open vSwitch CI 70cc8f
         int rta_oif;      /* Output interface index. */
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-        nlmsg = buf->data;
Open vSwitch CI 70cc8f
-
Open vSwitch CI 70cc8f
         memset(change, 0, sizeof *change);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+        ovs_list_init(&change->rd.nexthops);
Open vSwitch CI 70cc8f
+        rdnh = rtnh ? xzalloc(sizeof *rdnh) : &change->rd.primary_next_hop__;
Open vSwitch CI 70cc8f
+        ovs_list_insert(&change->rd.nexthops, &rdnh->nexthop_node);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+        rdnh->family = rtm->rtm_family;
Open vSwitch CI 70cc8f
         change->relevant = true;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
         if (rtm->rtm_scope == RT_SCOPE_NOWHERE) {
Open vSwitch CI 56d821
@@ -281,33 +313,33 @@ route_table_parse(struct ofpbuf *buf, void *change_)
Open vSwitch CI 70cc8f
             change->relevant = false;
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-        table_id = rtm->rtm_table;
Open vSwitch CI 70cc8f
+        change->rd.rta_table_id = rtm->rtm_table;
Open vSwitch CI 70cc8f
         if (attrs[RTA_TABLE]) {
Open vSwitch CI 70cc8f
-            table_id = nl_attr_get_u32(attrs[RTA_TABLE]);
Open vSwitch CI 70cc8f
-        }
Open vSwitch CI 70cc8f
-        /* Do not consider changes in non-standard routing tables. */
Open vSwitch CI 70cc8f
-        if (table_id
Open vSwitch CI 70cc8f
-            && table_id != RT_TABLE_DEFAULT
Open vSwitch CI 70cc8f
-            && table_id != RT_TABLE_MAIN
Open vSwitch CI 70cc8f
-            && table_id != RT_TABLE_LOCAL) {
Open vSwitch CI 70cc8f
-            change->relevant = false;
Open vSwitch CI 70cc8f
+            change->rd.rta_table_id = nl_attr_get_u32(attrs[RTA_TABLE]);
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
         change->nlmsg_type     = nlmsg->nlmsg_type;
Open vSwitch CI 70cc8f
-        change->rd.rtm_dst_len = rtm->rtm_dst_len + (ipv4 ? 96 : 0);
Open vSwitch CI 70cc8f
-        change->rd.local = rtm->rtm_type == RTN_LOCAL;
Open vSwitch CI 70cc8f
-        if (attrs[RTA_OIF]) {
Open vSwitch CI 70cc8f
-            rta_oif = nl_attr_get_u32(attrs[RTA_OIF]);
Open vSwitch CI 70cc8f
+        change->rd.rtm_dst_len = rtm->rtm_dst_len;
Open vSwitch CI 70cc8f
+        change->rd.rtm_protocol = rtm->rtm_protocol;
Open vSwitch CI 70cc8f
+        change->rd.rtn_local = rtm->rtm_type == RTN_LOCAL;
Open vSwitch CI 70cc8f
+        if (attrs[RTA_OIF] && rtnh) {
Open vSwitch CI 70cc8f
+            VLOG_DBG_RL(&rl, "unexpected RTA_OIF attribute while parsing "
Open vSwitch CI 70cc8f
+                             "nested RTA_MULTIPATH attributes");
Open vSwitch CI 70cc8f
+            goto error_out;
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 70cc8f
+        if (attrs[RTA_OIF] || rtnh) {
Open vSwitch CI 70cc8f
+            rta_oif = rtnh ? rtnh->rtnh_ifindex
Open vSwitch CI 70cc8f
+                           : nl_attr_get_u32(attrs[RTA_OIF]);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-            if (!if_indextoname(rta_oif, change->rd.ifname)) {
Open vSwitch CI 70cc8f
+            if (!if_indextoname(rta_oif, rdnh->ifname)) {
Open vSwitch CI 70cc8f
                 int error = errno;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-                VLOG_DBG_RL(&rl, "Could not find interface name[%u]: %s",
Open vSwitch CI 70cc8f
+                VLOG_DBG_RL(&rl, "could not find interface name[%u]: %s",
Open vSwitch CI 70cc8f
                             rta_oif, ovs_strerror(error));
Open vSwitch CI 70cc8f
                 if (error == ENXIO) {
Open vSwitch CI 70cc8f
                     change->relevant = false;
Open vSwitch CI 70cc8f
                 } else {
Open vSwitch CI 70cc8f
-                    return 0;
Open vSwitch CI 70cc8f
+                    goto error_out;
Open vSwitch CI 70cc8f
                 }
Open vSwitch CI 70cc8f
             }
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 56d821
@@ -337,40 +369,197 @@ route_table_parse(struct ofpbuf *buf, void *change_)
Open vSwitch CI 70cc8f
             if (ipv4) {
Open vSwitch CI 70cc8f
                 ovs_be32 gw;
Open vSwitch CI 70cc8f
                 gw = nl_attr_get_be32(attrs[RTA_GATEWAY]);
Open vSwitch CI 70cc8f
-                in6_addr_set_mapped_ipv4(&change->rd.rta_gw, gw);
Open vSwitch CI 70cc8f
+                in6_addr_set_mapped_ipv4(&rdnh->addr, gw);
Open vSwitch CI 70cc8f
             } else {
Open vSwitch CI 70cc8f
-                change->rd.rta_gw = nl_attr_get_in6_addr(attrs[RTA_GATEWAY]);
Open vSwitch CI 70cc8f
+                rdnh->addr = nl_attr_get_in6_addr(attrs[RTA_GATEWAY]);
Open vSwitch CI 70cc8f
             }
Open vSwitch CI 70cc8f
         }
Open vSwitch CI 70cc8f
         if (attrs[RTA_MARK]) {
Open vSwitch CI 70cc8f
-            change->rd.mark = nl_attr_get_u32(attrs[RTA_MARK]);
Open vSwitch CI 70cc8f
+            change->rd.rta_mark = nl_attr_get_u32(attrs[RTA_MARK]);
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 70cc8f
+        if (attrs[RTA_PRIORITY]) {
Open vSwitch CI 70cc8f
+            change->rd.rta_priority = nl_attr_get_u32(attrs[RTA_PRIORITY]);
Open vSwitch CI 56d821
+        }
Open vSwitch CI 70cc8f
+        if (attrs[RTA_VIA]) {
Open vSwitch CI 70cc8f
+            const struct rtvia *rtvia = nl_attr_get(attrs[RTA_VIA]);
Open vSwitch CI 70cc8f
+            ovs_be32 addr;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            if (attrs[RTA_GATEWAY]) {
Open vSwitch CI 70cc8f
+                VLOG_DBG_RL(&rl, "route message can not contain both "
Open vSwitch CI 70cc8f
+                                 "RTA_GATEWAY and RTA_VIA");
Open vSwitch CI 70cc8f
+                goto error_out;
Open vSwitch CI 70cc8f
+            }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            rdnh->family = rtvia->rtvia_family;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            switch (rdnh->family) {
Open vSwitch CI 70cc8f
+            case AF_INET:
Open vSwitch CI 70cc8f
+                if (nl_attr_get_size(attrs[RTA_VIA])
Open vSwitch CI 70cc8f
+                        - sizeof *rtvia < sizeof addr) {
Open vSwitch CI 70cc8f
+                    VLOG_DBG_RL(&rl, "got short message while parsing RTA_VIA "
Open vSwitch CI 70cc8f
+                                     "attribute for family AF_INET");
Open vSwitch CI 70cc8f
+                    goto error_out;
Open vSwitch CI 70cc8f
+                }
Open vSwitch CI 70cc8f
+                memcpy(&addr, rtvia->rtvia_addr, sizeof addr);
Open vSwitch CI 70cc8f
+                in6_addr_set_mapped_ipv4(&rdnh->addr, addr);
Open vSwitch CI 70cc8f
+                break;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            case AF_INET6:
Open vSwitch CI 70cc8f
+                if (nl_attr_get_size(attrs[RTA_VIA])
Open vSwitch CI 70cc8f
+                        - sizeof *rtvia < sizeof rdnh->addr) {
Open vSwitch CI 70cc8f
+                    VLOG_DBG_RL(&rl, "got short message while parsing RTA_VIA "
Open vSwitch CI 70cc8f
+                                     "attribute for family AF_INET6");
Open vSwitch CI 70cc8f
+                    goto error_out;
Open vSwitch CI 70cc8f
+                }
Open vSwitch CI 70cc8f
+                memcpy(&rdnh->addr, rtvia->rtvia_addr, sizeof rdnh->addr);
Open vSwitch CI 70cc8f
+                break;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            default:
Open vSwitch CI 70cc8f
+                VLOG_DBG_RL(&rl, "unsupported address family, %d, "
Open vSwitch CI 70cc8f
+                                 "in via attribute", rdnh->family);
Open vSwitch CI 70cc8f
+                goto error_out;
Open vSwitch CI 70cc8f
+            }
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 70cc8f
+        if (attrs[RTA_MULTIPATH]) {
Open vSwitch CI 70cc8f
+            const struct nlattr *nla;
Open vSwitch CI 70cc8f
+            size_t left;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            if (rtnh) {
Open vSwitch CI 70cc8f
+                VLOG_DBG_RL(&rl, "unexpected nested RTA_MULTIPATH attribute");
Open vSwitch CI 70cc8f
+                goto error_out;
Open vSwitch CI 70cc8f
+            }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            /* The change->rd->nexthops list is unconditionally populated with
Open vSwitch CI 70cc8f
+             * a single rdnh entry as we start parsing above.  Multiple
Open vSwitch CI 70cc8f
+             * branches above may access it or jump to error_out, and having it
Open vSwitch CI 70cc8f
+             * on the list is the only way to ensure proper cleanup.
Open vSwitch CI 70cc8f
+             *
Open vSwitch CI 70cc8f
+             * Getting to this point, we know that the above branches has not
Open vSwitch CI 70cc8f
+             * provided next hop information, because information about
Open vSwitch CI 70cc8f
+             * multiple next hops is encoded in the nested attributes after the
Open vSwitch CI 70cc8f
+             * RTA_MULTIPATH attribute.
Open vSwitch CI 70cc8f
+             *
Open vSwitch CI 70cc8f
+             * Before retrieving those we need to remove the empty rdnh entry
Open vSwitch CI 70cc8f
+             * from the list. */
Open vSwitch CI 70cc8f
+            route_data_destroy_nexthops__(&change->rd);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+            NL_NESTED_FOR_EACH (nla, left, attrs[RTA_MULTIPATH]) {
Open vSwitch CI 70cc8f
+                struct route_table_msg mp_change;
Open vSwitch CI 70cc8f
+                struct rtnexthop *mp_rtnh;
Open vSwitch CI 70cc8f
+                struct ofpbuf mp_buf;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+                ofpbuf_use_const(&mp_buf, nla, nla->nla_len);
Open vSwitch CI 70cc8f
+                mp_rtnh = ofpbuf_try_pull(&mp_buf, sizeof *mp_rtnh);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+                if (!mp_rtnh) {
Open vSwitch CI 70cc8f
+                    VLOG_DBG_RL(&rl, "got short message while parsing "
Open vSwitch CI 70cc8f
+                                     "multipath attribute");
Open vSwitch CI 70cc8f
+                    goto error_out;
Open vSwitch CI 70cc8f
+                }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+                if (!route_table_parse__(&mp_buf, 0, nlmsg, rtm, mp_rtnh,
Open vSwitch CI 70cc8f
+                                         &mp_change)) {
Open vSwitch CI 70cc8f
+                    goto error_out;
Open vSwitch CI 70cc8f
+                }
Open vSwitch CI 70cc8f
+                ovs_list_push_back_all(&change->rd.nexthops,
Open vSwitch CI 70cc8f
+                                       &mp_change.rd.nexthops);
Open vSwitch CI 70cc8f
+            }
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 56d821
+        if (route_type_needs_nexthop(rtm->rtm_type)
Open vSwitch CI 56d821
+            && !attrs[RTA_OIF] && !attrs[RTA_GATEWAY]
Open vSwitch CI 56d821
+            && !attrs[RTA_VIA] && !attrs[RTA_MULTIPATH]) {
Open vSwitch CI 70cc8f
+            VLOG_DBG_RL(&rl, "route message needs an RTA_OIF, RTA_GATEWAY, "
Open vSwitch CI 70cc8f
+                             "RTA_VIA or RTA_MULTIPATH attribute");
Open vSwitch CI 70cc8f
+            goto error_out;
Open vSwitch CI 70cc8f
+        }
Open vSwitch CI 70cc8f
+        /* Add any additional RTA attribute processing before RTA_MULTIPATH. */
Open vSwitch CI 56d821
+
Open vSwitch CI 56d821
+        /* Ensure that the change->rd->nexthops list is cleared in cases when
Open vSwitch CI 56d821
+         * the route does not need a next hop. */
Open vSwitch CI 56d821
+        if (!route_type_needs_nexthop(rtm->rtm_type)) {
Open vSwitch CI 56d821
+            route_data_destroy_nexthops__(&change->rd);
Open vSwitch CI 56d821
         }
Open vSwitch CI 70cc8f
     } else {
Open vSwitch CI 70cc8f
         VLOG_DBG_RL(&rl, "received unparseable rtnetlink route message");
Open vSwitch CI 70cc8f
-        return 0;
Open vSwitch CI 70cc8f
+        goto error_out;
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     /* Success. */
Open vSwitch CI 70cc8f
     return ipv4 ? RTNLGRP_IPV4_ROUTE : RTNLGRP_IPV6_ROUTE;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+error_out:
Open vSwitch CI 70cc8f
+    route_data_destroy(&change->rd);
Open vSwitch CI 70cc8f
+    return 0;
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+/* Parse Netlink message in buf, which is expected to contain a UAPI rtmsg
Open vSwitch CI 70cc8f
+ * header and associated route attributes.
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * Return RTNLGRP_IPV4_ROUTE or RTNLGRP_IPV6_ROUTE on success, and 0 on a parse
Open vSwitch CI 70cc8f
+ * error.
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * On success, memory may have been allocated, and it is the caller's
Open vSwitch CI 70cc8f
+ * responsibility to free it with a call to route_data_destroy().
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * In case of error, any allocated memory will be freed before returning. */
Open vSwitch CI 70cc8f
+int
Open vSwitch CI 70cc8f
+route_table_parse(struct ofpbuf *buf, void *change)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    struct nlmsghdr *nlmsg;
Open vSwitch CI 70cc8f
+    struct rtmsg *rtm;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    nlmsg = ofpbuf_at(buf, 0, NLMSG_HDRLEN);
Open vSwitch CI 70cc8f
+    rtm = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *rtm);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    if (!nlmsg || !rtm) {
Open vSwitch CI 70cc8f
+        return 0;
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    return route_table_parse__(buf, NLMSG_HDRLEN + sizeof *rtm,
Open vSwitch CI 70cc8f
+                               nlmsg, rtm, NULL, change);
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+static bool
Open vSwitch CI 70cc8f
+is_standard_table_id(uint32_t table_id)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    return !table_id
Open vSwitch CI 70cc8f
+           || table_id == RT_TABLE_DEFAULT
Open vSwitch CI 70cc8f
+           || table_id == RT_TABLE_MAIN
Open vSwitch CI 70cc8f
+           || table_id == RT_TABLE_LOCAL;
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 static void
Open vSwitch CI 70cc8f
-route_table_change(const struct route_table_msg *change OVS_UNUSED,
Open vSwitch CI 70cc8f
-                   void *aux OVS_UNUSED)
Open vSwitch CI 70cc8f
+route_table_change(struct route_table_msg *change, void *aux OVS_UNUSED)
Open vSwitch CI 70cc8f
 {
Open vSwitch CI 70cc8f
-    if (!change || change->relevant) {
Open vSwitch CI 70cc8f
+    if (!change
Open vSwitch CI 70cc8f
+        || (change->relevant
Open vSwitch CI 70cc8f
+            && is_standard_table_id(change->rd.rta_table_id))) {
Open vSwitch CI 70cc8f
         route_table_valid = false;
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
+    if (change) {
Open vSwitch CI 70cc8f
+        route_data_destroy(&change->rd);
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 static void
Open vSwitch CI 70cc8f
-route_table_handle_msg(const struct route_table_msg *change)
Open vSwitch CI 70cc8f
+route_table_handle_msg(const struct route_table_msg *change,
Open vSwitch CI 70cc8f
+                       void *aux OVS_UNUSED)
Open vSwitch CI 70cc8f
 {
Open vSwitch CI 70cc8f
-    if (change->relevant && change->nlmsg_type == RTM_NEWROUTE) {
Open vSwitch CI 70cc8f
+    if (change->relevant && change->nlmsg_type == RTM_NEWROUTE
Open vSwitch CI 70cc8f
+            && !ovs_list_is_empty(&change->rd.nexthops)) {
Open vSwitch CI 70cc8f
         const struct route_data *rd = &change->rd;
Open vSwitch CI 70cc8f
-
Open vSwitch CI 70cc8f
-        ovs_router_insert(rd->mark, &rd->rta_dst, rd->rtm_dst_len,
Open vSwitch CI 70cc8f
-                          rd->local, rd->ifname, &rd->rta_gw,
Open vSwitch CI 70cc8f
+        const struct route_data_nexthop *rdnh;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+        /* The ovs-router module currently does not implement lookup or
Open vSwitch CI 70cc8f
+         * storage for routes with multiple next hops.  For backwards
Open vSwitch CI 70cc8f
+         * compatibility, we use the first next hop. */
Open vSwitch CI 70cc8f
+        rdnh = CONTAINER_OF(ovs_list_front(&change->rd.nexthops),
Open vSwitch CI 70cc8f
+                            const struct route_data_nexthop, nexthop_node);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+        ovs_router_insert(rd->rta_mark, &rd->rta_dst,
Open vSwitch CI 70cc8f
+                          IN6_IS_ADDR_V4MAPPED(&rd->rta_dst)
Open vSwitch CI 70cc8f
+                          ? rd->rtm_dst_len + 96 : rd->rtm_dst_len,
Open vSwitch CI 70cc8f
+                          rd->rtn_local, rdnh->ifname, &rdnh->addr,
Open vSwitch CI 70cc8f
                           &rd->rta_prefsrc);
Open vSwitch CI 70cc8f
     }
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
diff --git a/lib/route-table.h b/lib/route-table.h
Open vSwitch CI 70cc8f
index 3a02d737ae..b805e84dd6 100644
Open vSwitch CI 70cc8f
--- a/lib/route-table.h
Open vSwitch CI 70cc8f
+++ b/lib/route-table.h
Open vSwitch CI 70cc8f
@@ -24,8 +24,133 @@
Open vSwitch CI 70cc8f
 #include <stdbool.h>
Open vSwitch CI 70cc8f
 #include <stdint.h>
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+#include "openvswitch/list.h"
Open vSwitch CI 70cc8f
+#include "openvswitch/ofpbuf.h"
Open vSwitch CI 70cc8f
 #include "openvswitch/types.h"
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+/*
Open vSwitch CI 70cc8f
+ * route-table, system route table synchronization for Open vSwitch.
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * Overview
Open vSwitch CI 70cc8f
+ * ========
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * The route-table module has two use cases:
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * 1) Internal use by Open vSwitch which together with the ovs-router module
Open vSwitch CI 70cc8f
+ *    implement route lookup for features such as flow based tunneling,
Open vSwitch CI 70cc8f
+ *    userspace tunneling, and sFlow.
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * 2) External use by projects such as Open Virtual Network (OVN), that use
Open vSwitch CI 70cc8f
+ *    Open vSwitch as a compile time library.
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * Typical External Usage
Open vSwitch CI 70cc8f
+ * ======================
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * static void
Open vSwitch CI 70cc8f
+ * my_handle_msg(const struct route_table_msg *change, void *data)
Open vSwitch CI 70cc8f
+ * {
Open vSwitch CI 70cc8f
+ *     struct my_data *aux = data;
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ *     if (data) {
Open vSwitch CI 70cc8f
+ *         aux->rta_dst = change->rd.rta_dst;
Open vSwitch CI 70cc8f
+ *     }
Open vSwitch CI 70cc8f
+ * }
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * static void
Open vSwitch CI 70cc8f
+ * my_route_table_dump(void)
Open vSwitch CI 70cc8f
+ * {
Open vSwitch CI 70cc8f
+ *     struct my_data *aux;
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ *     route_table_dump_one_table(RT_TABLE_MAIN, my_handle_msg, aux);
Open vSwitch CI 70cc8f
+ * }
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * static void
Open vSwitch CI 70cc8f
+ * my_route_table_change(struct route_table_msg *change, void *aux OVS_UNUSED);
Open vSwitch CI 70cc8f
+ * {
Open vSwitch CI 70cc8f
+ *     my_handle_msg(change, NULL);
Open vSwitch CI 70cc8f
+ *     route_data_destroy(&change->rd);
Open vSwitch CI 70cc8f
+ * }
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * static void
Open vSwitch CI 70cc8f
+ * my_init(void)
Open vSwitch CI 70cc8f
+ * {
Open vSwitch CI 70cc8f
+ *     static struct nln_notifier *route6_notifier = NULL;
Open vSwitch CI 70cc8f
+ *     static struct nln_notifier *route_notifier = NULL;
Open vSwitch CI 70cc8f
+ *     static struct route_table_msg nln_change;
Open vSwitch CI 70cc8f
+ *     static struct nln *nln = NULL;
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ *     nln = nln_create(NETLINK_ROUTE, route_table_parse, NULL);
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ *     route6_notifier =
Open vSwitch CI 70cc8f
+ *        nln_notifier_create(nln, RTNLGRP_IPV6_ROUTE,
Open vSwitch CI 70cc8f
+ *                            (nln_notify_func *) test_lib_route_table_change,
Open vSwitch CI 70cc8f
+ *                            NULL);
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ *     route_notifier =
Open vSwitch CI 70cc8f
+ *        nln_notifier_create(nln, RTNLGRP_IPV4_ROUTE,
Open vSwitch CI 70cc8f
+ *                            (nln_notify_func *) test_lib_route_table_change,
Open vSwitch CI 70cc8f
+ *                            NULL);
Open vSwitch CI 70cc8f
+ * }
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * Thread-safety
Open vSwitch CI 70cc8f
+ * =============
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * Assuming thread safe initialization of dependencies such as netlink socket,
Open vSwitch CI 70cc8f
+ * netlink notifier and so on, the functions in this module are thread safe.
Open vSwitch CI 70cc8f
+ */
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+/* Information about a next hop stored in a linked list with base in struct
Open vSwitch CI 70cc8f
+ * route_data.  Please refer to comment in struct route_data for details. */
Open vSwitch CI 70cc8f
+struct route_data_nexthop {
Open vSwitch CI 70cc8f
+    struct ovs_list nexthop_node;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    sa_family_t family;
Open vSwitch CI 70cc8f
+    struct in6_addr addr;
Open vSwitch CI 70cc8f
+    char ifname[IFNAMSIZ]; /* Interface name. */
Open vSwitch CI 70cc8f
+};
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+struct route_data {
Open vSwitch CI 70cc8f
+    /* Routes can have multiple next hops per destination.
Open vSwitch CI 70cc8f
+     *
Open vSwitch CI 70cc8f
+     * Each next hop has its own set of attributes such as address family,
Open vSwitch CI 70cc8f
+     * interface and IP address.
Open vSwitch CI 70cc8f
+     *
Open vSwitch CI 70cc8f
+     * When retrieving information about a route from the kernel, in the case
Open vSwitch CI 70cc8f
+     * of multiple next hops, information is provided as nested attributes.
Open vSwitch CI 70cc8f
+     *
Open vSwitch CI 70cc8f
+     * A linked list with struct route_data_nexthop entries is used to store
Open vSwitch CI 70cc8f
+     * this information as we parse each attribute.
Open vSwitch CI 70cc8f
+     *
Open vSwitch CI 70cc8f
+     * For the common case of one next hop, the nexthops list will contain a
Open vSwitch CI 70cc8f
+     * single entry pointing to the struct route_data primary_next_hop__
Open vSwitch CI 70cc8f
+     * element.
Open vSwitch CI 70cc8f
+     *
Open vSwitch CI 70cc8f
+     * Any dynamically allocated list elements MUST be freed with a call to the
Open vSwitch CI 70cc8f
+     * route_data_destroy function. */
Open vSwitch CI 70cc8f
+    struct ovs_list nexthops;
Open vSwitch CI 70cc8f
+    struct route_data_nexthop primary_next_hop__;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    /* Copied from struct rtmsg. */
Open vSwitch CI 70cc8f
+    unsigned char rtm_dst_len;
Open vSwitch CI 70cc8f
+    unsigned char rtm_protocol;
Open vSwitch CI 70cc8f
+    bool rtn_local;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    /* Extracted from Netlink attributes. */
Open vSwitch CI 70cc8f
+    struct in6_addr rta_dst;     /* 0 if missing. */
Open vSwitch CI 70cc8f
+    struct in6_addr rta_prefsrc; /* 0 if missing. */
Open vSwitch CI 70cc8f
+    uint32_t rta_mark;           /* 0 if missing. */
Open vSwitch CI 70cc8f
+    uint32_t rta_table_id;       /* 0 if missing. */
Open vSwitch CI 70cc8f
+    uint32_t rta_priority;       /* 0 if missing. */
Open vSwitch CI 70cc8f
+};
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+/* A digested version of a route message sent down by the kernel to indicate
Open vSwitch CI 70cc8f
+ * that a route has changed. */
Open vSwitch CI 70cc8f
+struct route_table_msg {
Open vSwitch CI 70cc8f
+    bool relevant;        /* Should this message be processed? */
Open vSwitch CI 70cc8f
+    uint16_t nlmsg_type;  /* e.g. RTM_NEWROUTE, RTM_DELROUTE. */
Open vSwitch CI 70cc8f
+    struct route_data rd; /* Data parsed from this message. */
Open vSwitch CI 70cc8f
+};
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 uint64_t route_table_get_change_seq(void);
Open vSwitch CI 70cc8f
 void route_table_init(void);
Open vSwitch CI 70cc8f
 void route_table_run(void);
Open vSwitch CI 70cc8f
@@ -33,4 +158,13 @@ void route_table_wait(void);
Open vSwitch CI 70cc8f
 bool route_table_fallback_lookup(const struct in6_addr *ip6_dst,
Open vSwitch CI 70cc8f
                                  char name[],
Open vSwitch CI 70cc8f
                                  struct in6_addr *gw6);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+typedef void route_table_handle_msg_callback(const struct route_table_msg *,
Open vSwitch CI 70cc8f
+                                             void *aux);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+bool route_table_dump_one_table(uint32_t id,
Open vSwitch CI 70cc8f
+                                route_table_handle_msg_callback *,
Open vSwitch CI 70cc8f
+                                void *aux);
Open vSwitch CI 70cc8f
+int route_table_parse(struct ofpbuf *, void *change);
Open vSwitch CI 70cc8f
+void route_data_destroy(struct route_data *);
Open vSwitch CI 70cc8f
 #endif /* route-table.h */
Open vSwitch CI 1a3c29
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
Open vSwitch CI 1a3c29
index 4cc7001a5b..e59ff17ade 100644
Open vSwitch CI 1a3c29
--- a/ofproto/ofproto-dpif-xlate.c
Open vSwitch CI 1a3c29
+++ b/ofproto/ofproto-dpif-xlate.c
Open vSwitch CI 1a3c29
@@ -6938,7 +6938,8 @@ rewrite_flow_push_nsh(struct xlate_ctx *ctx,
Open vSwitch CI 1a3c29
                                "supported for packet type (%d,0x%x)",
Open vSwitch CI 1a3c29
                                pt_ns(packet_type), pt_ns_type(packet_type));
Open vSwitch CI 1a3c29
             ctx->error = XLATE_UNSUPPORTED_PACKET_TYPE;
Open vSwitch CI 1a3c29
-            return buf;
Open vSwitch CI 1a3c29
+            ofpbuf_delete(buf);
Open vSwitch CI 1a3c29
+            return NULL;
Open vSwitch CI 1a3c29
     }
Open vSwitch CI 1a3c29
     /* Note that we have matched on packet_type! */
Open vSwitch CI 1a3c29
     wc->masks.packet_type = OVS_BE32_MAX;
Open vSwitch CI 03492a
diff --git a/ovsdb/ovsdb-server.c b/ovsdb/ovsdb-server.c
Open vSwitch CI 03492a
index fbc7ad5efe..aa2e27d844 100644
Open vSwitch CI 03492a
--- a/ovsdb/ovsdb-server.c
Open vSwitch CI 03492a
+++ b/ovsdb/ovsdb-server.c
Open vSwitch CI 03492a
@@ -504,7 +504,7 @@ add_database_config(struct shash *db_conf, const char *opt,
Open vSwitch CI 03492a
 
Open vSwitch CI 03492a
     conf = shash_replace_nocopy(db_conf, filename, conf);
Open vSwitch CI 03492a
     if (conf) {
Open vSwitch CI 03492a
-        VLOG_WARN("Duplicate database configuration: %s", filename);
Open vSwitch CI 03492a
+        VLOG_WARN("Duplicate database configuration: %s", opt);
Open vSwitch CI 03492a
         db_config_destroy(conf);
Open vSwitch CI 03492a
     }
Open vSwitch CI 03492a
 }
Open vSwitch CI 70cc8f
diff --git a/python/ovs/flowviz/odp/graph.py b/python/ovs/flowviz/odp/graph.py
Open vSwitch CI 70cc8f
index 4d1fb7493c..c9734efece 100644
Open vSwitch CI 70cc8f
--- a/python/ovs/flowviz/odp/graph.py
Open vSwitch CI 70cc8f
+++ b/python/ovs/flowviz/odp/graph.py
Open vSwitch CI 70cc8f
@@ -14,16 +14,26 @@
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 """ Defines a Datapath Graph using graphviz. """
Open vSwitch CI 70cc8f
 import colorsys
Open vSwitch CI 70cc8f
-import graphviz
Open vSwitch CI 70cc8f
 import random
Open vSwitch CI 70cc8f
+import sys
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 from ovs.flowviz.odp.html import HTMLTree, HTMLFormatter
Open vSwitch CI 70cc8f
 from ovs.flowviz.odp.tree import FlowTree
Open vSwitch CI 70cc8f
 from ovs.flowviz.process import FileProcessor
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+try:
Open vSwitch CI 70cc8f
+    import graphviz
Open vSwitch CI 70cc8f
+except ImportError:
Open vSwitch CI 70cc8f
+    graphviz = None
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 class GraphProcessor(FileProcessor):
Open vSwitch CI 70cc8f
     def __init__(self, opts):
Open vSwitch CI 70cc8f
+        if graphviz is None:
Open vSwitch CI 70cc8f
+            print("ERROR: The graph sub-command depends on the graphviz "
Open vSwitch CI 70cc8f
+                  "Python library, which does not appear to be installed.",
Open vSwitch CI 70cc8f
+                  file=sys.stderr)
Open vSwitch CI 70cc8f
+            sys.exit(1)
Open vSwitch CI 70cc8f
         super().__init__(opts, "odp")
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
     def start_file(self, name, filename):
Open vSwitch CI 56d821
diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
Open vSwitch CI 56d821
index 715cbf7aa7..26c0f6ec48 100644
Open vSwitch CI 56d821
--- a/rhel/openvswitch-fedora.spec.in
Open vSwitch CI 56d821
+++ b/rhel/openvswitch-fedora.spec.in
Open vSwitch CI 56d821
@@ -148,7 +148,7 @@ License: ASL 2.0
Open vSwitch CI 56d821
 This provides shared library, libopenswitch.so and the openvswitch header
Open vSwitch CI 56d821
 files needed to build an external application.
Open vSwitch CI 56d821
 
Open vSwitch CI 56d821
-%if 0%{?rhel} > 7 || 0%{?fedora} > 28
Open vSwitch CI 56d821
+%if 0%{?rhel} > 7 || (0%{?fedora} > 28 && 0%{?fedora} < 41)
Open vSwitch CI 56d821
 %package -n network-scripts-%{name}
Open vSwitch CI 56d821
 Summary: Open vSwitch legacy network service support
Open vSwitch CI 56d821
 License: ASL 2.0
Open vSwitch CI 56d821
@@ -436,7 +436,7 @@ fi
Open vSwitch CI 56d821
 %exclude %{_libdir}/*.la
Open vSwitch CI 56d821
 %exclude %{_libdir}/*.a
Open vSwitch CI 56d821
 
Open vSwitch CI 56d821
-%if 0%{?rhel} > 7 || 0%{?fedora} > 28
Open vSwitch CI 56d821
+%if 0%{?rhel} > 7 || (0%{?fedora} > 28 && 0%{?fedora} < 41)
Open vSwitch CI 56d821
 %files -n network-scripts-%{name}
Open vSwitch CI 56d821
 %{_sysconfdir}/sysconfig/network-scripts/ifup-ovs
Open vSwitch CI 56d821
 %{_sysconfdir}/sysconfig/network-scripts/ifdown-ovs
Open vSwitch CI 56d821
@@ -463,7 +463,7 @@ fi
Open vSwitch CI 56d821
 %{_unitdir}/ovs-vswitchd.service
Open vSwitch CI 56d821
 %{_unitdir}/ovs-delete-transient-ports.service
Open vSwitch CI 56d821
 %{_datadir}/openvswitch/scripts/openvswitch.init
Open vSwitch CI 56d821
-%if ! (0%{?rhel} > 7 || 0%{?fedora} > 28)
Open vSwitch CI 56d821
+%if ! (0%{?rhel} > 7 || (0%{?fedora} > 28 && 0%{?fedora} < 41))
Open vSwitch CI 56d821
 %{_sysconfdir}/sysconfig/network-scripts/ifup-ovs
Open vSwitch CI 56d821
 %{_sysconfdir}/sysconfig/network-scripts/ifdown-ovs
Open vSwitch CI 56d821
 %endif
Open vSwitch CI 70cc8f
diff --git a/rhel/usr_lib_systemd_system_openvswitch-ipsec.service b/rhel/usr_lib_systemd_system_openvswitch-ipsec.service
Open vSwitch CI 70cc8f
index 92dad44f93..913598f080 100644
Open vSwitch CI 70cc8f
--- a/rhel/usr_lib_systemd_system_openvswitch-ipsec.service
Open vSwitch CI 70cc8f
+++ b/rhel/usr_lib_systemd_system_openvswitch-ipsec.service
Open vSwitch CI 70cc8f
@@ -6,8 +6,11 @@ After=openvswitch.service
Open vSwitch CI 70cc8f
 [Service]
Open vSwitch CI 70cc8f
 Type=forking
Open vSwitch CI 70cc8f
 PIDFile=/run/openvswitch/ovs-monitor-ipsec.pid
Open vSwitch CI 70cc8f
-ExecStart=/usr/share/openvswitch/scripts/ovs-ctl \
Open vSwitch CI 70cc8f
-                    --ike-daemon=libreswan start-ovs-ipsec
Open vSwitch CI 70cc8f
+Restart=on-failure
Open vSwitch CI 70cc8f
+EnvironmentFile=/etc/openvswitch/default.conf
Open vSwitch CI 70cc8f
+EnvironmentFile=-/etc/sysconfig/openvswitch
Open vSwitch CI 70cc8f
+ExecStart=/usr/share/openvswitch/scripts/ovs-ctl --no-monitor \
Open vSwitch CI 70cc8f
+                    --ike-daemon=libreswan start-ovs-ipsec $OPTIONS
Open vSwitch CI 70cc8f
 ExecStop=/usr/share/openvswitch/scripts/ovs-ctl stop-ovs-ipsec
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 [Install]
Open vSwitch CI 70cc8f
diff --git a/rhel/usr_share_openvswitch_scripts_systemd_sysconfig.template b/rhel/usr_share_openvswitch_scripts_systemd_sysconfig.template
Open vSwitch CI 70cc8f
index c467d02db9..63833c4d8e 100644
Open vSwitch CI 70cc8f
--- a/rhel/usr_share_openvswitch_scripts_systemd_sysconfig.template
Open vSwitch CI 70cc8f
+++ b/rhel/usr_share_openvswitch_scripts_systemd_sysconfig.template
Open vSwitch CI 70cc8f
@@ -25,6 +25,9 @@
Open vSwitch CI 70cc8f
 #   --ovs-vswitchd-options='-vconsole:dbg -vfile:dbg'
Open vSwitch CI 70cc8f
 #   --ovsdb-server-options='-vconsole:dbg -vfile:dbg'
Open vSwitch CI 70cc8f
 #
Open vSwitch CI 70cc8f
+# Or to start with non-root IPsec config file:
Open vSwitch CI 70cc8f
+#   --ovs-monitor-ipsec-options='--ipsec-conf=/etc/ipsec.d/ovs.conf --root-ipsec-conf=/etc/ipsec.conf'
Open vSwitch CI 70cc8f
+#
Open vSwitch CI 70cc8f
 OPTIONS=""
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 # Uncomment and set the OVS User/Group value
Open vSwitch CI 70cc8f
diff --git a/tests/automake.mk b/tests/automake.mk
Open vSwitch CI 70cc8f
index edfc2cb335..59f5387612 100644
Open vSwitch CI 70cc8f
--- a/tests/automake.mk
Open vSwitch CI 70cc8f
+++ b/tests/automake.mk
Open vSwitch CI 70cc8f
@@ -498,6 +498,7 @@ endif
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 if LINUX
Open vSwitch CI 70cc8f
 tests_ovstest_SOURCES += \
Open vSwitch CI 70cc8f
+	tests/test-lib-route-table.c \
Open vSwitch CI 70cc8f
 	tests/test-netlink-conntrack.c \
Open vSwitch CI 70cc8f
 	tests/test-netlink-policy.c \
Open vSwitch CI 70cc8f
 	tests/test-psample.c
Open vSwitch CI 70cc8f
diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
Open vSwitch CI 70cc8f
index 36cea6aa95..60060ee2e0 100644
Open vSwitch CI 70cc8f
--- a/tests/dpif-netdev.at
Open vSwitch CI 70cc8f
+++ b/tests/dpif-netdev.at
Open vSwitch CI 70cc8f
@@ -658,11 +658,11 @@ OVS_VSWITCHD_START(
Open vSwitch CI 70cc8f
                      other-config:datapath-id=1234 fail-mode=secure])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 AT_CHECK([ovs-vsctl get interface p1 status | sed -n 's/^{\(.*\).*}$/\1/p'], [0], [dnl
Open vSwitch CI 70cc8f
-tx_geneve_tso_offload="false", tx_ip_csum_offload="false", tx_out_ip_csum_offload="false", tx_out_udp_csum_offload="false", tx_sctp_csum_offload="false", tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", tx_udp_csum_offload="false", tx_vxlan_tso_offload="false"
Open vSwitch CI 70cc8f
+tx_geneve_tso_offload="false", tx_gre_tso_offload="false", tx_ip_csum_offload="false", tx_out_ip_csum_offload="false", tx_out_udp_csum_offload="false", tx_sctp_csum_offload="false", tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", tx_udp_csum_offload="false", tx_vxlan_tso_offload="false"
Open vSwitch CI 70cc8f
 ], [])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 AT_CHECK([ovs-vsctl get interface br0 status | sed -n 's/^{\(.*\).*}$/\1/p'], [0], [dnl
Open vSwitch CI 70cc8f
-tx_geneve_tso_offload="false", tx_ip_csum_offload="false", tx_out_ip_csum_offload="false", tx_out_udp_csum_offload="false", tx_sctp_csum_offload="false", tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", tx_udp_csum_offload="false", tx_vxlan_tso_offload="false"
Open vSwitch CI 70cc8f
+tx_geneve_tso_offload="false", tx_gre_tso_offload="false", tx_ip_csum_offload="false", tx_out_ip_csum_offload="false", tx_out_udp_csum_offload="false", tx_sctp_csum_offload="false", tx_tcp_csum_offload="false", tx_tcp_seg_offload="false", tx_udp_csum_offload="false", tx_vxlan_tso_offload="false"
Open vSwitch CI 70cc8f
 ], [])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 OVS_VSWITCHD_STOP
Open vSwitch CI 70cc8f
@@ -937,15 +937,26 @@ AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy \
Open vSwitch CI 70cc8f
                        options:csum=true ofport_request=4 \
Open vSwitch CI 70cc8f
                     -- add-port int-br t4 -- set Interface t4 type=geneve \
Open vSwitch CI 70cc8f
                        options:remote_ip=2001:cafe::93 options:key=123 \
Open vSwitch CI 70cc8f
-                       options:csum=true ofport_request=5], [0])
Open vSwitch CI 70cc8f
+                       options:csum=true ofport_request=5 \
Open vSwitch CI 70cc8f
+                    -- add-port int-br t5 -- set Interface t5 type=gre \
Open vSwitch CI 70cc8f
+                       options:remote_ip=2001:cafe::93 options:key=123 \
Open vSwitch CI 70cc8f
+                       options:csum=true ofport_request=6 \
Open vSwitch CI 70cc8f
+                    -- add-port int-br t6 -- set Interface t6 type=gre \
Open vSwitch CI 70cc8f
+                       options:remote_ip=1.1.2.92 options:key=123 \
Open vSwitch CI 70cc8f
+                       options:csum=false ofport_request=7], [0])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-flow_s="eth(src=8a:bf:7e:2f:05:84,dst=0a:8f:39:4f:e0:73),eth_type(0x0800),
Open vSwitch CI 70cc8f
-        ipv4(src=192.168.123.2,dst=192.168.123.1,proto=6,tos=1,ttl=64,frag=no),
Open vSwitch CI 70cc8f
-        tcp(src=54392,dst=5201),tcp_flags(ack)"
Open vSwitch CI 70cc8f
+dnl The final tunnel intentionally has checksum turned off to exercise a
Open vSwitch CI 70cc8f
+dnl different code path, there is no GRE checksum offload anyways.
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-flow_s_v6="eth(src=8a:bf:7e:2f:05:84,dst=0a:8f:39:4f:e0:73),eth_type(0x86dd),
Open vSwitch CI 70cc8f
-           ipv6(src=2001:cafe::88,dst=2001:cafe::92,proto=6),
Open vSwitch CI 70cc8f
-           tcp(src=54392,dst=5201),tcp_flags(ack)"
Open vSwitch CI 70cc8f
+m4_define([IPV4_TSO], [m4_join([,],
Open vSwitch CI 70cc8f
+  [eth(src=8a:bf:7e:2f:05:84,dst=0a:8f:39:4f:e0:73),eth_type(0x0800)],
Open vSwitch CI 70cc8f
+  [ipv4(src=192.168.123.2,dst=192.168.123.1,proto=6,tos=1,ttl=64,frag=no)],
Open vSwitch CI 70cc8f
+  [tcp(src=54392,dst=5201),tcp_flags(ack)])])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+m4_define([IPV6_TSO], [m4_join([,],
Open vSwitch CI 70cc8f
+  [eth(src=8a:bf:7e:2f:05:84,dst=0a:8f:39:4f:e0:73),eth_type(0x86dd)],
Open vSwitch CI 70cc8f
+  [ipv6(src=2001:cafe::88,dst=2001:cafe::92,proto=6)],
Open vSwitch CI 70cc8f
+  [tcp(src=54392,dst=5201),tcp_flags(ack)])])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 dnl Setup dummy interface tunnel connectivity.
Open vSwitch CI 70cc8f
 AT_CHECK([ovs-appctl netdev-dummy/ip4addr br1 1.1.2.88/24], [0], [OK
Open vSwitch CI 70cc8f
@@ -968,9 +979,9 @@ AT_CHECK([ovs-vsctl set Interface p1 options:tx_pcap=p1.pcap -- \
Open vSwitch CI 70cc8f
                     set Interface int-br options:ol_ip_csum_set_good=false -- \
Open vSwitch CI 70cc8f
                     set Interface int-br options:ol_tso_segsz=500])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-AT_CHECK([ovs-appctl netdev-dummy/receive int-br "in_port(2),${flow_s}" \
Open vSwitch CI 70cc8f
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "IPV4_TSO" \
Open vSwitch CI 70cc8f
           --len 2054])
Open vSwitch CI 70cc8f
-AT_CHECK([ovs-appctl netdev-dummy/receive int-br "in_port(2),${flow_s_v6}" \
Open vSwitch CI 70cc8f
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br "IPV6_TSO" \
Open vSwitch CI 70cc8f
           --len 2074])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 dnl Check that first we have the following packets:
Open vSwitch CI 70cc8f
@@ -984,10 +995,26 @@ dnl - IPv6 Geneve tunnel with IPv4 payload
Open vSwitch CI 70cc8f
 dnl - IPv6 Geneve tunnel with IPv6 payload
Open vSwitch CI 70cc8f
 dnl - IPv6 Geneve tunnel with IPv4 payload
Open vSwitch CI 70cc8f
 dnl - IPv6 Geneve tunnel with IPv6 payload
Open vSwitch CI 70cc8f
+dnl - IPv4 GRE tunnel with IPv4 payload
Open vSwitch CI 70cc8f
+dnl - IPv4 GRE tunnel with IPv6 payload
Open vSwitch CI 70cc8f
+dnl - IPv6 GRE tunnel with IPv4 payload
Open vSwitch CI 70cc8f
+dnl - IPv6 GRE tunnel with IPv6 payload
Open vSwitch CI 70cc8f
 dnl These are sorted since OVS may send payloads to the tunnels in any order.
Open vSwitch CI 70cc8f
 zero400=$(printf '0%.0s' $(seq 800))
Open vSwitch CI 70cc8f
 zero100=$(printf '0%.0s' $(seq 200))
Open vSwitch CI 70cc8f
 AT_CHECK_UNQUOTED([ovs-pcap p1.pcap | sort], [0], [dnl
Open vSwitch CI 70cc8f
+[aabbcc000001aa55aa55000308004500025a00004000402f31c0010102580101025c200065580000007b0a8f394fe0738abf]dnl
Open vSwitch CI 70cc8f
+[7e2f058486dd60000000020806002001cafe0000000000000000000000882001cafe000000000000000000000092d4781451]dnl
Open vSwitch CI 70cc8f
+[000000000000000050100000edfd0000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000001aa55aa55000308004500025a00014000402f31bf010102580101025c200065580000007b0a8f394fe0738abf]dnl
Open vSwitch CI 70cc8f
+[7e2f058486dd60000000020806002001cafe0000000000000000000000882001cafe000000000000000000000092d4781451]dnl
Open vSwitch CI 70cc8f
+[000001f40000000050100000ec090000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000001aa55aa55000308004500025a00024000402f31be010102580101025c200065580000007b0a8f394fe0738abf]dnl
Open vSwitch CI 70cc8f
+[7e2f058486dd60000000020806002001cafe0000000000000000000000882001cafe000000000000000000000092d4781451]dnl
Open vSwitch CI 70cc8f
+[000003e80000000050100000ea150000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000001aa55aa55000308004500025a00034000402f31bd010102580101025c200065580000007b0a8f394fe0738abf]dnl
Open vSwitch CI 70cc8f
+[7e2f058486dd60000000020806002001cafe0000000000000000000000882001cafe000000000000000000000092d4781451]dnl
Open vSwitch CI 70cc8f
+[000005dc0000000050100000e8210000${zero100}${zero400}]
Open vSwitch CI 70cc8f
 [aabbcc000001aa55aa55000308004500026200004000401131d6010102580101025ce01312b5024e5f360800000000007b00]dnl
Open vSwitch CI 70cc8f
 [0a8f394fe0738abf7e2f058486dd60000000020806002001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
 [00000092d4781451000000000000000050100000edfd0000${zero100}${zero400}]
Open vSwitch CI 70cc8f
@@ -1012,6 +1039,18 @@ AT_CHECK_UNQUOTED([ovs-pcap p1.pcap | sort], [0], [dnl
Open vSwitch CI 70cc8f
 [aabbcc000001aa55aa55000308004500026200034000401131d3010102580101025ce01317c1024efcd10000655800007b00]dnl
Open vSwitch CI 70cc8f
 [0a8f394fe0738abf7e2f058486dd60000000020806002001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
 [00000092d4781451000005dc0000000050100000e8210000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000001aa55aa55000308004501024600004000402f31d3010102580101025c200065580000007b0a8f394fe0738abf]dnl
Open vSwitch CI 70cc8f
+[7e2f058408004501021c0000000040060187c0a87b02c0a87b01d47814510000000000000000501000004dc20000]dnl
Open vSwitch CI 70cc8f
+[${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000001aa55aa55000308004501024600014000402f31d2010102580101025c200065580000007b0a8f394fe0738abf]dnl
Open vSwitch CI 70cc8f
+[7e2f058408004501021c0001000040060186c0a87b02c0a87b01d4781451000001f400000000501000004bce0000]dnl
Open vSwitch CI 70cc8f
+[${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000001aa55aa55000308004501024600024000402f31d1010102580101025c200065580000007b0a8f394fe0738abf]dnl
Open vSwitch CI 70cc8f
+[7e2f058408004501021c0002000040060185c0a87b02c0a87b01d4781451000003e8000000005010000049da0000]dnl
Open vSwitch CI 70cc8f
+[${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000001aa55aa55000308004501024600034000402f31d0010102580101025c200065580000007b0a8f394fe0738abf]dnl
Open vSwitch CI 70cc8f
+[7e2f058408004501021c0003000040060184c0a87b02c0a87b01d4781451000005dc000000005010000047e60000]dnl
Open vSwitch CI 70cc8f
+[${zero100}${zero400}]
Open vSwitch CI 70cc8f
 [aabbcc000001aa55aa55000308004501024e00004000401131e9010102580101025ce01312b5023abd990800000000007b00]dnl
Open vSwitch CI 70cc8f
 [0a8f394fe0738abf7e2f058408004501021c0000000040060187c0a87b02c0a87b01d4781451000000000000000050100000]dnl
Open vSwitch CI 70cc8f
 [4dc20000${zero100}${zero400}]
Open vSwitch CI 70cc8f
@@ -1036,6 +1075,18 @@ AT_CHECK_UNQUOTED([ovs-pcap p1.pcap | sort], [0], [dnl
Open vSwitch CI 70cc8f
 [aabbcc000001aa55aa55000308004501024e00034000401131e6010102580101025ce01317c1023a5b350000655800007b00]dnl
Open vSwitch CI 70cc8f
 [0a8f394fe0738abf7e2f058408004501021c0003000040060184c0a87b02c0a87b01d4781451000005dc0000000050100000]dnl
Open vSwitch CI 70cc8f
 [47e60000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000006aa55aa55000386dd60000000024a2f402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[00000093a0006558da8e00000000007b0a8f394fe0738abf7e2f058486dd60000000020806002001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[000000882001cafe000000000000000000000092d4781451000005dc0000000050100000e8210000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000006aa55aa55000386dd60000000024a2f402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[00000093a0006558dc8200000000007b0a8f394fe0738abf7e2f058486dd60000000020806002001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[000000882001cafe000000000000000000000092d4781451000003e80000000050100000ea150000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000006aa55aa55000386dd60000000024a2f402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[00000093a0006558de7600000000007b0a8f394fe0738abf7e2f058486dd60000000020806002001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[000000882001cafe000000000000000000000092d4781451000001f40000000050100000ec090000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000006aa55aa55000386dd60000000024a2f402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[00000093a0006558e06a00000000007b0a8f394fe0738abf7e2f058486dd60000000020806002001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[000000882001cafe000000000000000000000092d4781451000000000000000050100000edfd0000${zero100}${zero400}]
Open vSwitch CI 70cc8f
 [aabbcc000006aa55aa55000386dd60000000024e11402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
 [00000093e01312b5024e8ed10800000000007b000a8f394fe0738abf7e2f058486dd60000000020806002001cafe00000000]dnl
Open vSwitch CI 70cc8f
 [00000000000000882001cafe000000000000000000000092d4781451000000000000000050100000edfd0000${zero100}]dnl
Open vSwitch CI 70cc8f
@@ -1068,6 +1119,18 @@ AT_CHECK_UNQUOTED([ovs-pcap p1.pcap | sort], [0], [dnl
Open vSwitch CI 70cc8f
 [00000093e01317c1024e2c6d0000655800007b000a8f394fe0738abf7e2f058486dd60000000020806002001cafe00000000]dnl
Open vSwitch CI 70cc8f
 [00000000000000882001cafe000000000000000000000092d4781451000005dc0000000050100000e8210000${zero100}]dnl
Open vSwitch CI 70cc8f
 [${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000006aa55aa55000386dd6010000002362f402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[00000093a00065583a4e00000000007b0a8f394fe0738abf7e2f058408004501021c0003000040060184c0a87b02c0a87b01]dnl
Open vSwitch CI 70cc8f
+[d4781451000005dc000000005010000047e60000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000006aa55aa55000386dd6010000002362f402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[00000093a00065583c4300000000007b0a8f394fe0738abf7e2f058408004501021c0002000040060185c0a87b02c0a87b01]dnl
Open vSwitch CI 70cc8f
+[d4781451000003e8000000005010000049da0000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000006aa55aa55000386dd6010000002362f402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[00000093a00065583e3800000000007b0a8f394fe0738abf7e2f058408004501021c0001000040060186c0a87b02c0a87b01]dnl
Open vSwitch CI 70cc8f
+[d4781451000001f400000000501000004bce0000${zero100}${zero400}]
Open vSwitch CI 70cc8f
+[aabbcc000006aa55aa55000386dd6010000002362f402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
+[00000093a0006558402d00000000007b0a8f394fe0738abf7e2f058408004501021c0000000040060187c0a87b02c0a87b01]dnl
Open vSwitch CI 70cc8f
+[d47814510000000000000000501000004dc20000${zero100}${zero400}]
Open vSwitch CI 70cc8f
 [aabbcc000006aa55aa55000386dd60100000023a11402001cafe0000000000000000000000882001cafe0000000000000000]dnl
Open vSwitch CI 70cc8f
 [00000093e01312b5023aed340800000000007b000a8f394fe0738abf7e2f058408004501021c0000000040060187c0a87b02]dnl
Open vSwitch CI 70cc8f
 [c0a87b01d47814510000000000000000501000004dc20000${zero100}${zero400}]
Open vSwitch CI 70cc8f
diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at
Open vSwitch CI 70cc8f
index 779a054e8c..3cd49d7a71 100644
Open vSwitch CI 70cc8f
--- a/tests/ofproto-macros.at
Open vSwitch CI 70cc8f
+++ b/tests/ofproto-macros.at
Open vSwitch CI 70cc8f
@@ -171,9 +171,9 @@ strip_eth () {
Open vSwitch CI 70cc8f
 # 'recirc=<recirc_id>' respectively.  This should make output easier to
Open vSwitch CI 70cc8f
 # compare.
Open vSwitch CI 70cc8f
 strip_recirc() {
Open vSwitch CI 70cc8f
-   sed 's/recirc_id([[x0-9]]*)/recirc_id(<recirc>)/
Open vSwitch CI 70cc8f
-        s/recirc_id=[[x0-9]]*/recirc_id=<recirc>/
Open vSwitch CI 70cc8f
-        s/recirc([[x0-9]]*)/recirc(<recirc>)/'
Open vSwitch CI 70cc8f
+   sed 's/recirc_id([[x0-9a-f]]*)/recirc_id(<recirc>)/
Open vSwitch CI 70cc8f
+        s/recirc_id=[[x0-9a-f]]*/recirc_id=<recirc>/
Open vSwitch CI 70cc8f
+        s/recirc([[x0-9a-f]]*)/recirc(<recirc>)/'
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 # Strips dp_hash from output.
Open vSwitch CI 70cc8f
diff --git a/tests/system-kmod-macros.at b/tests/system-kmod-macros.at
Open vSwitch CI 70cc8f
index a48bd532a0..7a7a19f7e4 100644
Open vSwitch CI 70cc8f
--- a/tests/system-kmod-macros.at
Open vSwitch CI 70cc8f
+++ b/tests/system-kmod-macros.at
Open vSwitch CI 70cc8f
@@ -202,6 +202,14 @@ m4_define([DPCTL_CHECK_FRAGMENTATION_FAIL],
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 ])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+# OVS_CHECK_FRAG_LARGE
Open vSwitch CI 70cc8f
+#
Open vSwitch CI 70cc8f
+# This check isn't valid for kernel
Open vSwitch CI 70cc8f
+m4_define([OVS_CHECK_FRAG_LARGE],
Open vSwitch CI 70cc8f
+[
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 # OVS_CHECK_MIN_KERNEL([minversion], [minsublevel])
Open vSwitch CI 70cc8f
 #
Open vSwitch CI 70cc8f
 # Skip test if kernel version falls below minversion.minsublevel
Open vSwitch CI ee4d11
diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at
Open vSwitch CI ee4d11
index 78c6f5d7ec..32c0d2f2a1 100644
Open vSwitch CI ee4d11
--- a/tests/system-offloads-traffic.at
Open vSwitch CI ee4d11
+++ b/tests/system-offloads-traffic.at
Open vSwitch CI ee4d11
@@ -1016,4 +1016,34 @@ AT_CHECK(
Open vSwitch CI ee4d11
    stdout])
Open vSwitch CI ee4d11
 
Open vSwitch CI ee4d11
 OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI ee4d11
-AT_CLEANUP
Open vSwitch CI ee4d11
\ No newline at end of file
Open vSwitch CI ee4d11
+AT_CLEANUP
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+AT_SETUP([offloads - 802.1ad should be offloaded])
Open vSwitch CI ee4d11
+OVS_TRAFFIC_VSWITCHD_START(
Open vSwitch CI ee4d11
+  [], [], [-- set Open_vSwitch . other_config:hw-offload=true])
Open vSwitch CI ee4d11
+OVS_CHECK_8021AD()
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+ADD_NAMESPACES(at_ns0, at_ns1)
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
Open vSwitch CI ee4d11
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+ADD_SVLAN(p0, at_ns0, 4094, "10.255.2.1/24")
Open vSwitch CI ee4d11
+ADD_SVLAN(p1, at_ns1, 4094, "10.255.2.2/24")
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+ADD_CVLAN(p0.4094, at_ns0, 100, "10.2.2.1/24")
Open vSwitch CI ee4d11
+ADD_CVLAN(p1.4094, at_ns1, 100, "10.2.2.2/24")
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+AT_CHECK([ovs-ofctl add-flow br0 "priority=1 action=normal"])
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+OVS_WAIT_UNTIL([ip netns exec at_ns0 ping -c 1 10.2.2.2])
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "eth_type(0x0800)" | DUMP_CLEAN_SORTED], [0], [dnl
Open vSwitch CI ee4d11
+in_port(2),eth(macs),eth_type(0x88a8),vlan(vid=4094,pcp=0),encap(eth_type(0x0800)), packets:0, bytes:0, used:0.001s, actions:output
Open vSwitch CI ee4d11
+in_port(3),eth(macs),eth_type(0x88a8),vlan(vid=4094,pcp=0),encap(eth_type(0x0800)), packets:0, bytes:0, used:0.001s, actions:output
Open vSwitch CI ee4d11
+])
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+AT_CHECK([ovs-appctl dpctl/dump-flows type=ovs | grep "eth_type(0x0800)" | DUMP_CLEAN_SORTED], [0], [])
Open vSwitch CI ee4d11
+
Open vSwitch CI ee4d11
+OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI ee4d11
+AT_CLEANUP
Open vSwitch CI 70cc8f
diff --git a/tests/system-route.at b/tests/system-route.at
Open vSwitch CI 70cc8f
index c0ecad6cfb..66bfd0e8ed 100644
Open vSwitch CI 70cc8f
--- a/tests/system-route.at
Open vSwitch CI 70cc8f
+++ b/tests/system-route.at
Open vSwitch CI 70cc8f
@@ -65,6 +65,26 @@ Cached: fc00:db8:beef::13/128 dev br0 GW fc00:db8:cafe::1 SRC fc00:db8:cafe::2])
Open vSwitch CI 70cc8f
 OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
 AT_CLEANUP
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+AT_SETUP([ovs-route - add system route - ipv4 via ipv6 nexthop])
Open vSwitch CI 70cc8f
+AT_KEYWORDS([route])
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_START()
Open vSwitch CI 70cc8f
+AT_CHECK([ovs-vsctl set bridge br0 other-config:hwaddr=00:53:00:00:00:42])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set br0 up])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CHECK([ip addr add 192.168.9.2/24 dev br0], [0], [stdout])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CHECK([ip route add 192.168.10.12/32 \
Open vSwitch CI 70cc8f
+          via inet6 fe80::253:ff:fe00:51 dev br0], [0], [stdout])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CHECK([ovs-appctl revalidator/wait])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | \
Open vSwitch CI 70cc8f
+                      grep -E '192.168.10.12/32' | sort], [dnl
Open vSwitch CI 70cc8f
+Cached: 192.168.10.12/32 dev br0 GW fe80::253:ff:fe00:51 SRC fe80::253:ff:fe00:42])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
+AT_CLEANUP
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 dnl Checks that OVS doesn't use routes from non-standard tables.
Open vSwitch CI 70cc8f
 AT_SETUP([ovs-route - route tables])
Open vSwitch CI 70cc8f
 AT_KEYWORDS([route])
Open vSwitch CI 70cc8f
@@ -91,8 +111,13 @@ Cached: 10.0.0.0/24 dev p1-route SRC 10.0.0.17
Open vSwitch CI 70cc8f
 Cached: 10.0.0.17/32 dev p1-route SRC 10.0.0.17 local
Open vSwitch CI 70cc8f
 Cached: 10.0.0.18/32 dev p1-route SRC 10.0.0.17])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+dnl Negative check for custom routing table using route-table library.
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | grep rta_table_id:\ 42], [1])
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | grep rta_table_id:\ 1042], [1])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 dnl Add a route to a custom routing table and check that OVS doesn't cache it.
Open vSwitch CI 70cc8f
 AT_CHECK([ip route add 10.0.0.19/32 dev p1-route table 42])
Open vSwitch CI 70cc8f
+AT_CHECK([ip route add 10.0.0.20/32 dev p1-route table 1042])
Open vSwitch CI 70cc8f
 AT_CHECK([ip route show table 42 | grep 'p1-route' | grep -q '10.0.0.19'])
Open vSwitch CI 70cc8f
 dnl Give the main thread a chance to act.
Open vSwitch CI 70cc8f
 AT_CHECK([ovs-appctl revalidator/wait])
Open vSwitch CI 70cc8f
@@ -102,6 +127,11 @@ Cached: 10.0.0.0/24 dev p1-route SRC 10.0.0.17
Open vSwitch CI 70cc8f
 Cached: 10.0.0.17/32 dev p1-route SRC 10.0.0.17 local
Open vSwitch CI 70cc8f
 Cached: 10.0.0.18/32 dev p1-route SRC 10.0.0.17
Open vSwitch CI 70cc8f
 ])
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | \
Open vSwitch CI 70cc8f
+          awk '/rta_table_id:.*42/{print$1" "$15" "$16}' | sort], [0], [dnl
Open vSwitch CI 70cc8f
+10.0.0.19/32 rta_table_id: 42
Open vSwitch CI 70cc8f
+10.0.0.20/32 rta_table_id: 1042
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 dnl Delete a route from the main table and check that OVS removes the route
Open vSwitch CI 70cc8f
 dnl from the cache.
Open vSwitch CI 70cc8f
@@ -128,3 +158,177 @@ OVS_WAIT_UNTIL([test $(ovs-appctl ovs/route/show | grep -c 'p1-route') -eq 0 ])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
 AT_CLEANUP
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_SETUP([ovs-route - add system route with multiple nexthop - ipv4])
Open vSwitch CI 70cc8f
+AT_KEYWORDS([route])
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_START()
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Create tap ports.
Open vSwitch CI 70cc8f
+AT_CHECK([ip tuntap add name p1-route mode tap])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set p1-route up])
Open vSwitch CI 70cc8f
+on_exit 'ip link del p1-route'
Open vSwitch CI 70cc8f
+AT_CHECK([ip tuntap add name p2-route mode tap])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set p2-route up])
Open vSwitch CI 70cc8f
+on_exit 'ip link del p2-route'
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CHECK([ip addr add 192.168.42.10/24 dev p1-route], [0], [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ip addr add 192.168.51.10/24 dev p2-route], [0], [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ip route add 172.16.42.0/24 nexthop via 192.168.42.1 \
Open vSwitch CI 70cc8f
+          dev p1-route nexthop via 192.168.51.1 dev p2-route], [0], [stdout])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl NOTE: At the time of this writing, it is expected that only the first route
Open vSwitch CI 70cc8f
+dnl       will be stored in ovs-router.
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E '172.16.42.0/24' | \
Open vSwitch CI 70cc8f
+                      sort], [dnl
Open vSwitch CI 70cc8f
+Cached: 172.16.42.0/24 dev p1-route GW 192.168.42.1 SRC 192.168.42.10])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Confirm that both nexthops are available when using the route-table library
Open vSwitch CI 70cc8f
+dnl directly.
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | grep 172.16.42.0.*nexthop | sort],
Open vSwitch CI 70cc8f
+         [0], [dnl
Open vSwitch CI 70cc8f
+    172.16.42.0/24 nexthop family: AF_INET addr: 192.168.42.1 ifname: p1-route
Open vSwitch CI 70cc8f
+    172.16.42.0/24 nexthop family: AF_INET addr: 192.168.51.1 ifname: p2-route
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
+AT_CLEANUP
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_SETUP([ovs-route - add system route - ipv4 via multiple ipv6 nexthop])
Open vSwitch CI 70cc8f
+AT_KEYWORDS([route])
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_START()
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Create tap ports.
Open vSwitch CI 70cc8f
+AT_CHECK([ip tuntap add name p1-route mode tap])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set p1-route up])
Open vSwitch CI 70cc8f
+on_exit 'ip link del p1-route'
Open vSwitch CI 70cc8f
+AT_CHECK([ip tuntap add name p2-route mode tap])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set p2-route up])
Open vSwitch CI 70cc8f
+on_exit 'ip link del p2-route'
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CHECK([ip -6 addr add fc00:db8:dead::10/64 dev p1-route], [0], [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ip -6 addr add fc00:db8:beef::10/64 dev p2-route], [0], [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ip route add 172.16.42.0/24 nexthop via inet6 fc00:db8:dead::1 \
Open vSwitch CI 70cc8f
+          dev p1-route nexthop via inet6 fc00:db8:beef::1 dev p2-route],
Open vSwitch CI 70cc8f
+          [0], [stdout])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl NOTE: At the time of this writing, it is expected that only the first route
Open vSwitch CI 70cc8f
+dnl       will be stored in ovs-router.
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | grep -E '172.16.42.0/24' | \
Open vSwitch CI 70cc8f
+                      sort], [dnl
Open vSwitch CI 70cc8f
+Cached: 172.16.42.0/24 dev p1-route GW fc00:db8:dead::1 SRC fc00:db8:dead::10])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Confirm that both nexthops are available when using the route-table library
Open vSwitch CI 70cc8f
+dnl directly.
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | grep 172.16.42.0.*nexthop | sort],
Open vSwitch CI 70cc8f
+         [0], [dnl
Open vSwitch CI 70cc8f
+    172.16.42.0/24 nexthop family: AF_INET6 addr: fc00:db8:beef::1 ifname: p2-route
Open vSwitch CI 70cc8f
+    172.16.42.0/24 nexthop family: AF_INET6 addr: fc00:db8:dead::1 ifname: p1-route
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
+AT_CLEANUP
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_SETUP([ovs-route - add system route with multiple nexthop - ipv6])
Open vSwitch CI 70cc8f
+AT_KEYWORDS([route])
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_START()
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Create tap ports.
Open vSwitch CI 70cc8f
+AT_CHECK([ip tuntap add name p1-route mode tap])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set p1-route up])
Open vSwitch CI 70cc8f
+on_exit 'ip link del p1-route'
Open vSwitch CI 70cc8f
+AT_CHECK([ip tuntap add name p2-route mode tap])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set p2-route up])
Open vSwitch CI 70cc8f
+on_exit 'ip link del p2-route'
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CHECK([ip -6 addr add fc00:db8:dead::10/64 dev p1-route], [0], [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ip -6 addr add fc00:db8:beef::10/64 dev p2-route], [0], [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ip -6 route add fc00:db8:cafe::/64 nexthop via fc00:db8:dead::1 \
Open vSwitch CI 70cc8f
+          dev p1-route nexthop via fc00:db8:beef::1 dev p2-route],
Open vSwitch CI 70cc8f
+         [0], [stdout])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl NOTE: At the time of this writing, it is expected that only the first route
Open vSwitch CI 70cc8f
+dnl       will be stored in ovs-router.
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL_EQUAL([ovs-appctl ovs/route/show | \
Open vSwitch CI 70cc8f
+                      grep -E 'fc00:db8:cafe::/64' | sort], [dnl
Open vSwitch CI 70cc8f
+Cached: fc00:db8:cafe::/64 dev p1-route GW fc00:db8:dead::1 SRC fc00:db8:dead::10])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Confirm that both nexthops are available when using the route-table library
Open vSwitch CI 70cc8f
+dnl directly.
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | grep fc00:db8:cafe::.*nexthop | \
Open vSwitch CI 70cc8f
+          sort], [0], [dnl
Open vSwitch CI 70cc8f
+    fc00:db8:cafe::/64 nexthop family: AF_INET6 addr: fc00:db8:beef::1 ifname: p2-route
Open vSwitch CI 70cc8f
+    fc00:db8:cafe::/64 nexthop family: AF_INET6 addr: fc00:db8:dead::1 ifname: p1-route
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
+AT_CLEANUP
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_SETUP([route-table - exported functions work for netlink-notifier])
Open vSwitch CI 70cc8f
+AT_KEYWORDS([route])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Create tap ports.
Open vSwitch CI 70cc8f
+AT_CHECK([ip tuntap add name p1-route mode tap])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set p1-route up])
Open vSwitch CI 70cc8f
+on_exit 'ip link del p1-route'
Open vSwitch CI 70cc8f
+AT_CHECK([ip tuntap add name p2-route mode tap])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set p2-route up])
Open vSwitch CI 70cc8f
+on_exit 'ip link del p2-route'
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CHECK([ip -6 addr add fc00:db8:dead::10/64 dev p1-route], [0], [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ip -6 addr add fc00:db8:beef::10/64 dev p2-route], [0], [stdout])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-monitor 'ip route add 172.16.42.0/24 \
Open vSwitch CI 70cc8f
+          nexthop via inet6 fc00:db8:dead::1 dev p1-route \
Open vSwitch CI 70cc8f
+          nexthop via inet6 fc00:db8:beef::1 dev p2-route' | \
Open vSwitch CI 70cc8f
+          grep 172.16.42.0.*nexthop | sort], [0], [dnl
Open vSwitch CI 70cc8f
+    172.16.42.0/24 nexthop family: AF_INET6 addr: fc00:db8:beef::1 ifname: p2-route
Open vSwitch CI 70cc8f
+    172.16.42.0/24 nexthop family: AF_INET6 addr: fc00:db8:dead::1 ifname: p1-route
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CLEANUP
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_SETUP([route-table - route attributes])
Open vSwitch CI 70cc8f
+AT_KEYWORDS([route])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Create tap ports.
Open vSwitch CI 70cc8f
+AT_CHECK([ip tuntap add name p1-route mode tap])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set p1-route up])
Open vSwitch CI 70cc8f
+on_exit 'ip link del p1-route'
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Add ip address.
Open vSwitch CI 70cc8f
+AT_CHECK([ip addr add 10.0.0.17/24 dev p1-route], [0], [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | \
Open vSwitch CI 70cc8f
+          awk '/^10.0.0.17/{print$1" "$6" "$7}'], [0], [dnl
Open vSwitch CI 70cc8f
+10.0.0.17/32 rtm_protocol: RTPROT_KERNEL
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Add route.
Open vSwitch CI 70cc8f
+AT_CHECK([ip route add 192.168.10.12/32 dev p1-route via 10.0.0.18], [0],
Open vSwitch CI 70cc8f
+         [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | \
Open vSwitch CI 70cc8f
+          awk '/^192.168.10.12/{print$1" "$17" "$18}'], [0], [dnl
Open vSwitch CI 70cc8f
+192.168.10.12/32 rta_priority: 0
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | \
Open vSwitch CI 70cc8f
+          awk '/^192.168.10.12/{print$1" "$6" "$7}'], [0], [dnl
Open vSwitch CI 70cc8f
+192.168.10.12/32 rtm_protocol: RTPROT_BOOT
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Delete route.
Open vSwitch CI 70cc8f
+AT_CHECK([ip route del 192.168.10.12/32 dev p1-route via 10.0.0.18], [0],
Open vSwitch CI 70cc8f
+         [stdout])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Add route with priority.
Open vSwitch CI 70cc8f
+AT_CHECK([ip route add 192.168.10.12/32 dev p1-route via 10.0.0.18 metric 42],
Open vSwitch CI 70cc8f
+         [0], [stdout])
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | \
Open vSwitch CI 70cc8f
+          awk '/^192.168.10.12/{print$1" "$17" "$18}'], [0], [dnl
Open vSwitch CI 70cc8f
+192.168.10.12/32 rta_priority: 42
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+AT_CHECK([ovstest test-lib-route-table-dump | \
Open vSwitch CI 70cc8f
+          awk '/^192.168.10.12/{print$1" "$6" "$7}'], [0], [dnl
Open vSwitch CI 70cc8f
+192.168.10.12/32 rtm_protocol: RTPROT_BOOT
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CLEANUP
Open vSwitch CI 70cc8f
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
Open vSwitch CI 70cc8f
index 16de8da20f..04328db4cc 100644
Open vSwitch CI 70cc8f
--- a/tests/system-traffic.at
Open vSwitch CI 70cc8f
+++ b/tests/system-traffic.at
Open vSwitch CI 70cc8f
@@ -557,7 +557,6 @@ OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
 AT_CLEANUP
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 AT_SETUP([datapath - ping over gre tunnel])
Open vSwitch CI 70cc8f
-OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
Open vSwitch CI 70cc8f
 OVS_CHECK_GRE()
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 OVS_TRAFFIC_VSWITCHD_START()
Open vSwitch CI 70cc8f
@@ -615,8 +614,97 @@ OVS_WAIT_UNTIL([diff -q payload.bin udp_data])
Open vSwitch CI 70cc8f
 OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
 AT_CLEANUP
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+AT_SETUP([datapath - tcp over gre tunnel with software fallback])
Open vSwitch CI 70cc8f
+AT_SKIP_IF([test $HAVE_NC = no])
Open vSwitch CI 70cc8f
+AT_SKIP_IF([test $HAVE_TCPDUMP = no])
Open vSwitch CI 70cc8f
+OVS_CHECK_GRE()
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl This test is only valid with tso. If the kernel segments the packets, the
Open vSwitch CI 70cc8f
+dnl packet lengths in the final test will be different.
Open vSwitch CI 70cc8f
+m4_ifndef([CHECK_SYSTEM_TSO], [AT_SKIP_IF(:)])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_START()
Open vSwitch CI 70cc8f
+ADD_BR([br-underlay])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
Open vSwitch CI 70cc8f
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+ADD_NAMESPACES(at_ns0)
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Set up underlay link from host into the namespace using veth pair.
Open vSwitch CI 70cc8f
+ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24")
Open vSwitch CI 70cc8f
+AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set dev br-underlay up])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Test the case where one side has all checksum and TSO offload disabled.
Open vSwitch CI 70cc8f
+AT_CHECK([ethtool -K ovs-p0 tso off], [0], [ignore], [ignore])
Open vSwitch CI 70cc8f
+AT_CHECK([ethtool -K ovs-p0 sg off], [0], [ignore], [ignore])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Reinitialize.
Open vSwitch CI 70cc8f
+AT_CHECK([ovs-vsctl del-port ovs-p0])
Open vSwitch CI 70cc8f
+AT_CHECK([ovs-vsctl add-port br-underlay ovs-p0])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
Open vSwitch CI 70cc8f
+dnl linux device inside the namespace.
Open vSwitch CI 70cc8f
+ADD_OVS_TUNNEL([gre], [br0], [at_gre0], [172.31.1.1], [10.1.1.100/24])
Open vSwitch CI 70cc8f
+ADD_NATIVE_TUNNEL([gretap], [at_gre1], [at_ns0], [172.31.1.100], [10.1.1.1/24])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Set MTU for tunnel to generate 1500 byte packets.
Open vSwitch CI 70cc8f
+AT_CHECK([ip link set dev br0 mtu 1400])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl First, check the underlay.
Open vSwitch CI 70cc8f
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -W 2 172.31.1.100 | FORMAT_PING],
Open vSwitch CI 70cc8f
+              [0], [dnl
Open vSwitch CI 70cc8f
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Check that the tunnel is up.
Open vSwitch CI 70cc8f
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -W 2 10.1.1.100 | FORMAT_PING],
Open vSwitch CI 70cc8f
+              [0], [dnl
Open vSwitch CI 70cc8f
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Start tcpdump to capture the encapsulated packets.
Open vSwitch CI 70cc8f
+OVS_DAEMONIZE([tcpdump -i ovs-p0 -w p0.pcap], [tcpdump.pid])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Wait until the pcap is written, which happens after the interface
Open vSwitch CI 70cc8f
+dnl is opened by tcpdump.
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL([test -e p0.pcap])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Initialize the listener before it is needed.
Open vSwitch CI 70cc8f
+NETNS_DAEMONIZE([at_ns0], [nc -l 10.1.1.1 1234 > data2], [nc.pid])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Verify that ncat is ready.
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL([NS_EXEC([at_ns0], [netstat -ln | grep :1234])])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Large TCP transfer aimed towards ovs-p0, which has TSO disabled.
Open vSwitch CI 70cc8f
+AT_CHECK([dd if=/dev/urandom of=payload.bin bs=60000 count=1 2> /dev/null])
Open vSwitch CI 70cc8f
+AT_CHECK([nc $NC_EOF_OPT 10.1.1.1 1234 < payload.bin])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Wait until transfer completes before checking.
Open vSwitch CI 70cc8f
+OVS_WAIT_WHILE([kill -0 $(cat nc.pid)])
Open vSwitch CI 70cc8f
+AT_CHECK([diff -q payload.bin data2], [0])
Open vSwitch CI 70cc8f
+OVS_WAIT_WHILE([test $(stat -c %s p0.pcap) -le 68000 ])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Stop OVS and tcpdump and verify the results.
Open vSwitch CI 70cc8f
+AT_CHECK([kill -15 $(cat tcpdump.pid)])
Open vSwitch CI 70cc8f
+OVS_WAIT_WHILE([kill -0 $(cat tcpdump.pid)])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl The exact number of packets sent will vary, but we check that the largest
Open vSwitch CI 70cc8f
+dnl segments have the correct lengths and certain other fields.
Open vSwitch CI 70cc8f
+AT_CHECK([test $(ovs-pcap p0.pcap | grep -Ec dnl
Open vSwitch CI 70cc8f
+"^.{24}0800"dnl Ethernet
Open vSwitch CI 70cc8f
+"4500059e....4000..2f....ac1f0164ac1f0101"dnl IP(len=1450, DF, GRE, 172.31.1.100->172.31.1.1)
Open vSwitch CI 70cc8f
+"00006558"dnl GRE(flags=0, proto=0x6558)
Open vSwitch CI 70cc8f
+".{24}0800"dnl Ethernet
Open vSwitch CI 70cc8f
+"45000578....4000..06....0a0101640a010101"dnl IP(len=1400, DF, TCP, 10.1.1.100->10.1.1.1)
Open vSwitch CI 70cc8f
+"....04d2............................0000"dnl TCP(dport=1234
Open vSwitch CI 70cc8f
+) -ge 20])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
+AT_CLEANUP
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 AT_SETUP([datapath - ping over ip6gre L2 tunnel])
Open vSwitch CI 70cc8f
-OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
Open vSwitch CI 70cc8f
 OVS_CHECK_GRE()
Open vSwitch CI 70cc8f
 OVS_CHECK_ERSPAN()
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
@@ -651,6 +739,25 @@ dnl Okay, now check the overlay with different packet sizes
Open vSwitch CI 70cc8f
 NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -W 2 10.1.1.100 | FORMAT_PING], [0], [dnl
Open vSwitch CI 70cc8f
 3 packets transmitted, 3 received, 0% packet loss, time 0ms
Open vSwitch CI 70cc8f
 ])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Start ncat listeners.
Open vSwitch CI 70cc8f
+OVS_DAEMONIZE([nc -l 10.1.1.100 1234 > tcp_data], [nc.pid])
Open vSwitch CI 70cc8f
+NETNS_DAEMONIZE([at_ns0], [nc -l -u 10.1.1.1 4321 > udp_data], [nc2.pid])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Verify that ncat is ready.
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL([netstat -ln | grep :1234])
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL([NS_EXEC([at_ns0], [netstat -ln | grep :4321])])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Check large bidirectional TCP.
Open vSwitch CI 70cc8f
+AT_CHECK([dd if=/dev/urandom of=payload.bin bs=60000 count=1 2> /dev/null])
Open vSwitch CI 70cc8f
+NS_CHECK_EXEC([at_ns0], [nc $NC_EOF_OPT 10.1.1.100 1234 < payload.bin])
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL([diff -q payload.bin tcp_data])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+dnl Check UDP.
Open vSwitch CI 70cc8f
+AT_CHECK([dd if=/dev/urandom of=payload.bin bs=600 count=1 2> /dev/null])
Open vSwitch CI 70cc8f
+AT_CHECK([nc $NC_EOF_OPT -u 10.1.1.1 4321 < payload.bin])
Open vSwitch CI 70cc8f
+OVS_WAIT_UNTIL([diff -q payload.bin udp_data])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
 AT_CLEANUP
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
@@ -1191,7 +1298,6 @@ AT_CLEANUP
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 AT_SETUP([datapath - ping over gre tunnel by simulated packets])
Open vSwitch CI 70cc8f
 OVS_CHECK_XT()
Open vSwitch CI 70cc8f
-OVS_CHECK_MIN_KERNEL(3, 10)
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 OVS_TRAFFIC_VSWITCHD_START()
Open vSwitch CI 70cc8f
 AT_CHECK([ovs-vsctl -- set bridge br0 other-config:hwaddr=\"f2:ff:00:00:00:01\"])
Open vSwitch CI 70cc8f
@@ -2033,7 +2139,6 @@ dnl   ns1: connect to br0, with IP:10.1.1.2
Open vSwitch CI 70cc8f
 dnl   br-underlay: with IP: 172.31.1.100
Open vSwitch CI 70cc8f
 dnl   ns0: connect to br-underlay, with IP: 10.1.1.1
Open vSwitch CI 70cc8f
 AT_SETUP([datapath - truncate and output to gre tunnel by simulated packets])
Open vSwitch CI 70cc8f
-OVS_CHECK_MIN_KERNEL(3, 10)
Open vSwitch CI 70cc8f
 AT_SKIP_IF([test $HAVE_NC = no])
Open vSwitch CI 70cc8f
 CHECK_NO_TC_OFFLOAD()
Open vSwitch CI 70cc8f
 OVS_TRAFFIC_VSWITCHD_START()
Open vSwitch CI 70cc8f
@@ -2165,7 +2270,6 @@ dnl   br-underlay: with IP: 172.31.1.100
Open vSwitch CI 70cc8f
 dnl   ns0: connect to br-underlay, with IP: 10.1.1.1
Open vSwitch CI 70cc8f
 AT_SETUP([datapath - truncate and output to gre tunnel])
Open vSwitch CI 70cc8f
 AT_SKIP_IF([test $HAVE_NC = no])
Open vSwitch CI 70cc8f
-OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
Open vSwitch CI 70cc8f
 OVS_CHECK_GRE()
Open vSwitch CI 70cc8f
 CHECK_NO_TC_OFFLOAD()
Open vSwitch CI 70cc8f
 OVS_TRAFFIC_VSWITCHD_START()
Open vSwitch CI 70cc8f
@@ -4603,7 +4707,11 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -W 2 10.1.1.2 | FORMAT_PING
Open vSwitch CI 70cc8f
 dnl Check userspace conntrack fragmentation counters.
Open vSwitch CI 70cc8f
 DPCTL_CHECK_FRAGMENTATION_PASS()
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
+dnl Ipv4 max packet size fragmentation dropped.
Open vSwitch CI 70cc8f
+NS_EXEC([at_ns0], [ping -s 65507 -q -c 1 -W 0.5 10.1.1.2])
Open vSwitch CI 70cc8f
+OVS_CHECK_FRAG_LARGE()
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_STOP(["/Unsupported big reassembled v4 packet/d"])
Open vSwitch CI 70cc8f
 AT_CLEANUP
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 AT_SETUP([conntrack - IPv4 fragmentation expiry])
Open vSwitch CI 70cc8f
@@ -4897,7 +5005,11 @@ NS_CHECK_EXEC([at_ns0], [ping6 -s 3200 -q -c 3 -i 0.3 -W 2 fc00::2 | FORMAT_PING
Open vSwitch CI 70cc8f
 3 packets transmitted, 3 received, 0% packet loss, time 0ms
Open vSwitch CI 70cc8f
 ])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-OVS_TRAFFIC_VSWITCHD_STOP
Open vSwitch CI 70cc8f
+dnl Ipv6 max packet size fragmentation dropped.
Open vSwitch CI 70cc8f
+NS_EXEC([at_ns0], [ping6 -s 65487 -q -c 1 -W 0.5 fc00::2])
Open vSwitch CI 70cc8f
+OVS_CHECK_FRAG_LARGE()
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVS_TRAFFIC_VSWITCHD_STOP(["/Unsupported big reassembled v6 packet/d"])
Open vSwitch CI 70cc8f
 AT_CLEANUP
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 AT_SETUP([conntrack - IPv6 fragmentation expiry])
Open vSwitch CI 70cc8f
diff --git a/tests/system-userspace-macros.at b/tests/system-userspace-macros.at
Open vSwitch CI 70cc8f
index c1be973478..49b277a089 100644
Open vSwitch CI 70cc8f
--- a/tests/system-userspace-macros.at
Open vSwitch CI 70cc8f
+++ b/tests/system-userspace-macros.at
Open vSwitch CI 70cc8f
@@ -298,6 +298,14 @@ AT_CHECK([ovs-appctl dpctl/ipf-get-status -m | FORMAT_FRAG_LIST()], [], [dnl
Open vSwitch CI 70cc8f
 ])
Open vSwitch CI 70cc8f
 ])
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+# OVS_CHECK_FRAG_LARGE()
Open vSwitch CI 70cc8f
+#
Open vSwitch CI 70cc8f
+# The userspace needs to check that ipf larger fragments have occurred.
Open vSwitch CI 70cc8f
+m4_define([OVS_CHECK_FRAG_LARGE],
Open vSwitch CI 70cc8f
+[
Open vSwitch CI 70cc8f
+    OVS_WAIT_UNTIL([grep -Eq 'Unsupported big reassembled (v4|v6) packet' ovs-vswitchd.log])
Open vSwitch CI 70cc8f
+])
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 # OVS_CHECK_MIN_KERNEL([minversion], [maxversion])
Open vSwitch CI 70cc8f
 #
Open vSwitch CI 70cc8f
 # The userspace skips all tests that check kernel version.
Open vSwitch CI 70cc8f
diff --git a/tests/test-lib-route-table.c b/tests/test-lib-route-table.c
Open vSwitch CI 70cc8f
new file mode 100644
Open vSwitch CI 70cc8f
index 0000000000..61d97e06ff
Open vSwitch CI 70cc8f
--- /dev/null
Open vSwitch CI 70cc8f
+++ b/tests/test-lib-route-table.c
Open vSwitch CI 70cc8f
@@ -0,0 +1,149 @@
Open vSwitch CI 70cc8f
+/*
Open vSwitch CI 70cc8f
+ * Copyright (c) 2024 Canonical Ltd.
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * Licensed under the Apache License, Version 2.0 (the "License");
Open vSwitch CI 70cc8f
+ * you may not use this file except in compliance with the License.
Open vSwitch CI 70cc8f
+ * You may obtain a copy of the License at:
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ *     http://www.apache.org/licenses/LICENSE-2.0
Open vSwitch CI 70cc8f
+ *
Open vSwitch CI 70cc8f
+ * Unless required by applicable law or agreed to in writing, software
Open vSwitch CI 70cc8f
+ * distributed under the License is distributed on an "AS IS" BASIS,
Open vSwitch CI 70cc8f
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Open vSwitch CI 70cc8f
+ * See the License for the specific language governing permissions and
Open vSwitch CI 70cc8f
+ * limitations under the License.
Open vSwitch CI 70cc8f
+ */
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+#include <config.h>
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+#undef NDEBUG
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+#include <linux/rtnetlink.h>
Open vSwitch CI 70cc8f
+#include <stdio.h>
Open vSwitch CI 70cc8f
+#include <stdlib.h>
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+#include "netlink-notifier.h"
Open vSwitch CI 70cc8f
+#include "ovstest.h"
Open vSwitch CI 70cc8f
+#include "packets.h"
Open vSwitch CI 70cc8f
+#include "route-table.h"
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+static char *
Open vSwitch CI 70cc8f
+rt_prot_name(unsigned char p)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    /* We concentrate on the most used protocols, as they are the ones most
Open vSwitch CI 70cc8f
+     * likely to be defined in the build environment. */
Open vSwitch CI 70cc8f
+    return p == RTPROT_UNSPEC     ? "RTPROT_UNSPEC"     :
Open vSwitch CI 70cc8f
+           p == RTPROT_REDIRECT   ? "RTPROT_REDIRECT"   :
Open vSwitch CI 70cc8f
+           p == RTPROT_KERNEL     ? "RTPROT_KERNEL"     :
Open vSwitch CI 70cc8f
+           p == RTPROT_BOOT       ? "RTPROT_BOOT"       :
Open vSwitch CI 70cc8f
+           p == RTPROT_STATIC     ? "RTPROT_STATIC"     :
Open vSwitch CI 70cc8f
+           p == RTPROT_RA         ? "RTPROT_RA"         :
Open vSwitch CI 70cc8f
+           p == RTPROT_DHCP       ? "RTPROT_DHCP"       :
Open vSwitch CI 70cc8f
+           p == RTPROT_BGP        ? "RTPROT_BGP"        :
Open vSwitch CI 70cc8f
+           "UNKNOWN";
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+static char *
Open vSwitch CI 70cc8f
+rt_table_name(uint32_t id)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    static char tid[11] = "";
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    snprintf(tid, sizeof tid, "%"PRIu32, id);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    return id == RT_TABLE_UNSPEC  ? "RT_TABLE_UNSPEC"  :
Open vSwitch CI 70cc8f
+           id == RT_TABLE_COMPAT  ? "RT_TABLE_COMPAT"  :
Open vSwitch CI 70cc8f
+           id == RT_TABLE_DEFAULT ? "RT_TABLE_DEFAULT" :
Open vSwitch CI 70cc8f
+           id == RT_TABLE_MAIN    ? "RT_TABLE_MAIN"    :
Open vSwitch CI 70cc8f
+           id == RT_TABLE_LOCAL   ? "RT_TABLE_LOCAL"   :
Open vSwitch CI 70cc8f
+           tid;
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+static void
Open vSwitch CI 70cc8f
+test_lib_route_table_handle_msg(const struct route_table_msg *change,
Open vSwitch CI 70cc8f
+                                void *data OVS_UNUSED)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    struct ds nexthop_addr = DS_EMPTY_INITIALIZER;
Open vSwitch CI 70cc8f
+    struct ds rta_prefsrc = DS_EMPTY_INITIALIZER;
Open vSwitch CI 70cc8f
+    const struct route_data *rd = &change->rd;
Open vSwitch CI 70cc8f
+    struct ds rta_dst = DS_EMPTY_INITIALIZER;
Open vSwitch CI 70cc8f
+    const struct route_data_nexthop *rdnh;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    ipv6_format_mapped(&change->rd.rta_prefsrc, &rta_prefsrc);
Open vSwitch CI 70cc8f
+    ipv6_format_mapped(&change->rd.rta_dst, &rta_dst);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    printf("%s/%u relevant: %d nlmsg_type: %d rtm_protocol: %s (%u) "
Open vSwitch CI 70cc8f
+           "rtn_local: %d rta_prefsrc: %s rta_mark: %"PRIu32" "
Open vSwitch CI 70cc8f
+           "rta_table_id: %s rta_priority: %"PRIu32"\n",
Open vSwitch CI 70cc8f
+           ds_cstr(&rta_dst), rd->rtm_dst_len, change->relevant,
Open vSwitch CI 70cc8f
+           change->nlmsg_type, rt_prot_name(rd->rtm_protocol),
Open vSwitch CI 70cc8f
+           rd->rtm_protocol, rd->rtn_local, ds_cstr(&rta_prefsrc),
Open vSwitch CI 70cc8f
+           rd->rta_mark, rt_table_name(rd->rta_table_id), rd->rta_priority);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    LIST_FOR_EACH (rdnh, nexthop_node, &rd->nexthops) {
Open vSwitch CI 70cc8f
+        ds_clear(&nexthop_addr);
Open vSwitch CI 70cc8f
+        ipv6_format_mapped(&rdnh->addr, &nexthop_addr);
Open vSwitch CI 70cc8f
+        printf("    %s/%u nexthop family: %s addr: %s ifname: %s\n",
Open vSwitch CI 70cc8f
+               ds_cstr(&rta_dst), rd->rtm_dst_len,
Open vSwitch CI 70cc8f
+               rdnh->family == AF_INET ? "AF_INET" :
Open vSwitch CI 70cc8f
+               rdnh->family == AF_INET6 ? "AF_INET6" :
Open vSwitch CI 70cc8f
+               "UNKNOWN",
Open vSwitch CI 70cc8f
+               ds_cstr(&nexthop_addr),
Open vSwitch CI 70cc8f
+               rdnh->ifname);
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    ds_destroy(&nexthop_addr);
Open vSwitch CI 70cc8f
+    ds_destroy(&rta_prefsrc);
Open vSwitch CI 70cc8f
+    ds_destroy(&rta_dst);
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+static void
Open vSwitch CI 70cc8f
+test_lib_route_table_dump(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    route_table_dump_one_table(RT_TABLE_UNSPEC,
Open vSwitch CI 70cc8f
+                               test_lib_route_table_handle_msg,
Open vSwitch CI 70cc8f
+                               NULL);
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+static void
Open vSwitch CI 70cc8f
+test_lib_route_table_change(struct route_table_msg *change,
Open vSwitch CI 70cc8f
+                            void *aux OVS_UNUSED)
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    test_lib_route_table_handle_msg(change, NULL);
Open vSwitch CI 70cc8f
+    route_data_destroy(&change->rd);
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+static void
Open vSwitch CI 70cc8f
+test_lib_route_table_monitor(int argc, char *argv[])
Open vSwitch CI 70cc8f
+{
Open vSwitch CI 70cc8f
+    static struct nln_notifier *route6_notifier OVS_UNUSED;
Open vSwitch CI 70cc8f
+    static struct nln_notifier *route_notifier OVS_UNUSED;
Open vSwitch CI 70cc8f
+    static struct route_table_msg rtmsg;
Open vSwitch CI 70cc8f
+    static struct nln *nln OVS_UNUSED;
Open vSwitch CI 70cc8f
+    const char *cmd = argv[1];
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    if (argc != 2) {
Open vSwitch CI 70cc8f
+        printf("usage: ovstest %s 'ip route add ...'\n", argv[0]);
Open vSwitch CI 70cc8f
+        exit(EXIT_FAILURE);
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    nln = nln_create(NETLINK_ROUTE, route_table_parse, &rtmsg);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+    route_notifier =
Open vSwitch CI 70cc8f
+        nln_notifier_create(nln, RTNLGRP_IPV4_ROUTE,
Open vSwitch CI 70cc8f
+                            (nln_notify_func *) test_lib_route_table_change,
Open vSwitch CI 70cc8f
+                            NULL);
Open vSwitch CI 70cc8f
+    route6_notifier =
Open vSwitch CI 70cc8f
+        nln_notifier_create(nln, RTNLGRP_IPV6_ROUTE,
Open vSwitch CI 70cc8f
+                            (nln_notify_func *) test_lib_route_table_change,
Open vSwitch CI 70cc8f
+                            NULL);
Open vSwitch CI 70cc8f
+    nln_run(nln);
Open vSwitch CI 70cc8f
+    nln_wait(nln);
Open vSwitch CI 70cc8f
+    int rc = system(cmd);
Open vSwitch CI 70cc8f
+    if (rc) {
Open vSwitch CI 70cc8f
+        exit(rc);
Open vSwitch CI 70cc8f
+    }
Open vSwitch CI 70cc8f
+    nln_run(nln);
Open vSwitch CI 70cc8f
+}
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+OVSTEST_REGISTER("test-lib-route-table-monitor", test_lib_route_table_monitor);
Open vSwitch CI 70cc8f
+OVSTEST_REGISTER("test-lib-route-table-dump", test_lib_route_table_dump);
Open vSwitch CI 70cc8f
diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
Open vSwitch CI 70cc8f
index 57abd3a5b4..03a39337f5 100644
Open vSwitch CI 70cc8f
--- a/utilities/ovs-ctl.in
Open vSwitch CI 70cc8f
+++ b/utilities/ovs-ctl.in
Open vSwitch CI 70cc8f
@@ -242,15 +242,20 @@ start_forwarding () {
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 start_ovs_ipsec () {
Open vSwitch CI 70cc8f
+    set ${datadir}/scripts/ovs-monitor-ipsec unix:"$DB_SOCK"
Open vSwitch CI 70cc8f
+    set "$@" --log-file=${logdir}/ovs-monitor-ipsec.log
Open vSwitch CI 70cc8f
+    set "$@" --pidfile=${rundir}/ovs-monitor-ipsec.pid
Open vSwitch CI 70cc8f
+    set "$@" --detach
Open vSwitch CI 70cc8f
+    test X"$MONITOR" = Xno || set "$@" --monitor
Open vSwitch CI 70cc8f
+    set "$@" --ike-daemon=$IKE_DAEMON
Open vSwitch CI 70cc8f
     if test X$RESTART_IKE_DAEMON = Xno; then
Open vSwitch CI 70cc8f
-        no_restart="--no-restart-ike-daemon"
Open vSwitch CI 70cc8f
+        set "$@" --no-restart-ike-daemon
Open vSwitch CI 70cc8f
+    fi
Open vSwitch CI 70cc8f
+    if test X"$OVS_MONITOR_IPSEC_OPTIONS" != X; then
Open vSwitch CI 70cc8f
+        set "$@" $OVS_MONITOR_IPSEC_OPTIONS
Open vSwitch CI 70cc8f
     fi
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
-    ${datadir}/scripts/ovs-monitor-ipsec \
Open vSwitch CI 70cc8f
-        --pidfile=${rundir}/ovs-monitor-ipsec.pid \
Open vSwitch CI 70cc8f
-        --ike-daemon=$IKE_DAEMON \
Open vSwitch CI 70cc8f
-        $no_restart \
Open vSwitch CI 70cc8f
-        --log-file --detach --monitor unix:${rundir}/db.sock || return 1
Open vSwitch CI 70cc8f
+    action "Starting ovs-monitor-ipsec" "$@" || return 1
Open vSwitch CI 70cc8f
     return 0
Open vSwitch CI 70cc8f
 }
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
@@ -348,6 +353,7 @@ set_defaults () {
Open vSwitch CI 70cc8f
     OVS_VSWITCHD_WRAPPER=
Open vSwitch CI 70cc8f
     OVSDB_SERVER_OPTIONS=
Open vSwitch CI 70cc8f
     OVS_VSWITCHD_OPTIONS=
Open vSwitch CI 70cc8f
+    OVS_MONITOR_IPSEC_OPTIONS=
Open vSwitch CI 70cc8f
     OVSDB_SERVER_UMASK=
Open vSwitch CI 70cc8f
     OVS_VSWITCHD_UMASK=
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
@@ -463,6 +469,9 @@ Option for "start-ovs-ipsec":
Open vSwitch CI 70cc8f
       the IKE daemon for ipsec tunnels (either libreswan or strongswan)
Open vSwitch CI 70cc8f
   --no-restart-ike-daemon
Open vSwitch CI 70cc8f
       do not restart the IKE daemon on startup
Open vSwitch CI 70cc8f
+  --ovs-monitor-ipsec-options=OPTIONS
Open vSwitch CI 70cc8f
+      additional options for ovs-monitor-ipsec (example:
Open vSwitch CI 70cc8f
+      '--ipsec-conf=/etc/ipsec.d/ovs.conf --root-ipsec-conf=/etc/ipsec.conf')
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 Other options:
Open vSwitch CI 70cc8f
   -h, --help                  display this help message
Open vSwitch CI 993944
diff --git a/utilities/ovs-vsctl-bashcomp.bash b/utilities/ovs-vsctl-bashcomp.bash
Open vSwitch CI 993944
index c5ad24fb70..5313fa9d48 100644
Open vSwitch CI 993944
--- a/utilities/ovs-vsctl-bashcomp.bash
Open vSwitch CI 993944
+++ b/utilities/ovs-vsctl-bashcomp.bash
Open vSwitch CI 993944
@@ -32,11 +32,15 @@ _ovs_vsctl () {
Open vSwitch CI 993944
 # A bar (|) character in an argument means thing before bar OR thing
Open vSwitch CI 993944
 # after bar; for example, del-port can take a port or an interface.
Open vSwitch CI 993944
 
Open vSwitch CI 993944
-_OVS_VSCTL_COMMANDS="$(_ovs_vsctl --commands)"
Open vSwitch CI 993944
-
Open vSwitch CI 993944
-# This doesn't complete on short arguments, so it filters them out.
Open vSwitch CI 993944
-_OVS_VSCTL_OPTIONS="$(_ovs_vsctl --options | awk '/^--/ { print $0 }' \
Open vSwitch CI 993944
-                      | sed -e 's/\(.*\)=ARG/\1=/')"
Open vSwitch CI 993944
+_OVS_VSCTL_COMMANDS=
Open vSwitch CI 993944
+_OVS_VSCTL_OPTIONS=
Open vSwitch CI 993944
+if command -v ovs-vsctl > /dev/null; then
Open vSwitch CI 993944
+    _OVS_VSCTL_COMMANDS="$(_ovs_vsctl --commands)"
Open vSwitch CI 993944
+
Open vSwitch CI 993944
+    # This doesn't complete on short arguments, so it filters them out.
Open vSwitch CI 993944
+    _OVS_VSCTL_OPTIONS="$(_ovs_vsctl --options | awk '/^--/ { print $0 }' \
Open vSwitch CI 993944
+                          | sed -e 's/\(.*\)=ARG/\1=/')"
Open vSwitch CI 993944
+fi
Open vSwitch CI 993944
 IFS=$SAVE_IFS
Open vSwitch CI 993944
 
Open vSwitch CI 993944
 declare -A _OVS_VSCTL_PARSED_ARGS
Open vSwitch CI 70cc8f
diff --git a/dpdk/VERSION b/dpdk/VERSION
Open vSwitch CI 70cc8f
index 0a492611a0..9e2934aa34 100644
Open vSwitch CI 70cc8f
--- a/dpdk/VERSION
Open vSwitch CI 70cc8f
+++ b/dpdk/VERSION
Open vSwitch CI 70cc8f
@@ -1 +1 @@
Open vSwitch CI 70cc8f
-24.11.0
Open vSwitch CI 70cc8f
+24.11.1
Open vSwitch CI 70cc8f
diff --git a/dpdk/doc/guides/rel_notes/release_24_11.rst b/dpdk/doc/guides/rel_notes/release_24_11.rst
Open vSwitch CI 70cc8f
index 8486cd986f..f9df63141e 100644
Open vSwitch CI 70cc8f
--- a/dpdk/doc/guides/rel_notes/release_24_11.rst
Open vSwitch CI 70cc8f
+++ b/dpdk/doc/guides/rel_notes/release_24_11.rst
Open vSwitch CI 70cc8f
@@ -616,3 +616,22 @@ Tested Platforms
Open vSwitch CI 70cc8f
       * Firmware version: 2.14, 0x8000028c
Open vSwitch CI 70cc8f
       * Device id (pf): 8086:125b
Open vSwitch CI 70cc8f
       * Driver version(in-tree): 6.8.0-45-generic (Ubuntu24.04.1)(igc)
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+24.11.1 Release Notes
Open vSwitch CI 70cc8f
+---------------------
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+24.11.1 Fixes
Open vSwitch CI 70cc8f
+~~~~~~~~~~~~~
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+* net/virtio: fix Rx checksum calculation
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+24.11.1 Validation
Open vSwitch CI 70cc8f
+~~~~~~~~~~~~~~~~~~
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+* Tested by Red Hat validation team
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+24.11.1 Known Issues
Open vSwitch CI 70cc8f
+~~~~~~~~~~~~~~~~~~~~
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+* DPDK 24.11.1 contains DPDK 24.11 plus the fix for CVE-2024-11614 only
Open vSwitch CI c49a4a
diff --git a/dpdk/kernel/linux/uapi/linux/vduse.h b/dpdk/kernel/linux/uapi/linux/vduse.h
Open vSwitch CI c49a4a
new file mode 100644
Open vSwitch CI c49a4a
index 0000000000..11bd48c72c
Open vSwitch CI c49a4a
--- /dev/null
Open vSwitch CI c49a4a
+++ b/dpdk/kernel/linux/uapi/linux/vduse.h
Open vSwitch CI c49a4a
@@ -0,0 +1,353 @@
Open vSwitch CI c49a4a
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
Open vSwitch CI c49a4a
+#ifndef _UAPI_VDUSE_H_
Open vSwitch CI c49a4a
+#define _UAPI_VDUSE_H_
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+#include <linux/types.h>
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+#define VDUSE_BASE	0x81
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/* The ioctls for control device (/dev/vduse/control) */
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+#define VDUSE_API_VERSION	0
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/*
Open vSwitch CI c49a4a
+ * Get the version of VDUSE API that kernel supported (VDUSE_API_VERSION).
Open vSwitch CI c49a4a
+ * This is used for future extension.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+#define VDUSE_GET_API_VERSION	_IOR(VDUSE_BASE, 0x00, __u64)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/* Set the version of VDUSE API that userspace supported. */
Open vSwitch CI c49a4a
+#define VDUSE_SET_API_VERSION	_IOW(VDUSE_BASE, 0x01, __u64)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_dev_config - basic configuration of a VDUSE device
Open vSwitch CI c49a4a
+ * @name: VDUSE device name, needs to be NUL terminated
Open vSwitch CI c49a4a
+ * @vendor_id: virtio vendor id
Open vSwitch CI c49a4a
+ * @device_id: virtio device id
Open vSwitch CI c49a4a
+ * @features: virtio features
Open vSwitch CI c49a4a
+ * @vq_num: the number of virtqueues
Open vSwitch CI c49a4a
+ * @vq_align: the allocation alignment of virtqueue's metadata
Open vSwitch CI c49a4a
+ * @reserved: for future use, needs to be initialized to zero
Open vSwitch CI c49a4a
+ * @config_size: the size of the configuration space
Open vSwitch CI c49a4a
+ * @config: the buffer of the configuration space
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by VDUSE_CREATE_DEV ioctl to create VDUSE device.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_dev_config {
Open vSwitch CI c49a4a
+#define VDUSE_NAME_MAX	256
Open vSwitch CI c49a4a
+	char name[VDUSE_NAME_MAX];
Open vSwitch CI c49a4a
+	__u32 vendor_id;
Open vSwitch CI c49a4a
+	__u32 device_id;
Open vSwitch CI c49a4a
+	__u64 features;
Open vSwitch CI c49a4a
+	__u32 vq_num;
Open vSwitch CI c49a4a
+	__u32 vq_align;
Open vSwitch CI c49a4a
+	__u32 reserved[13];
Open vSwitch CI c49a4a
+	__u32 config_size;
Open vSwitch CI c49a4a
+	__u8 config[];
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/* Create a VDUSE device which is represented by a char device (/dev/vduse/$NAME) */
Open vSwitch CI c49a4a
+#define VDUSE_CREATE_DEV	_IOW(VDUSE_BASE, 0x02, struct vduse_dev_config)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/*
Open vSwitch CI c49a4a
+ * Destroy a VDUSE device. Make sure there are no more references
Open vSwitch CI c49a4a
+ * to the char device (/dev/vduse/$NAME).
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+#define VDUSE_DESTROY_DEV	_IOW(VDUSE_BASE, 0x03, char[VDUSE_NAME_MAX])
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/* The ioctls for VDUSE device (/dev/vduse/$NAME) */
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_iotlb_entry - entry of IOTLB to describe one IOVA region [start, last]
Open vSwitch CI c49a4a
+ * @offset: the mmap offset on returned file descriptor
Open vSwitch CI c49a4a
+ * @start: start of the IOVA region
Open vSwitch CI c49a4a
+ * @last: last of the IOVA region
Open vSwitch CI c49a4a
+ * @perm: access permission of the IOVA region
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by VDUSE_IOTLB_GET_FD ioctl to find an overlapped IOVA region.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_iotlb_entry {
Open vSwitch CI c49a4a
+	__u64 offset;
Open vSwitch CI c49a4a
+	__u64 start;
Open vSwitch CI c49a4a
+	__u64 last;
Open vSwitch CI c49a4a
+#define VDUSE_ACCESS_RO 0x1
Open vSwitch CI c49a4a
+#define VDUSE_ACCESS_WO 0x2
Open vSwitch CI c49a4a
+#define VDUSE_ACCESS_RW 0x3
Open vSwitch CI c49a4a
+	__u8 perm;
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/*
Open vSwitch CI c49a4a
+ * Find the first IOVA region that overlaps with the range [start, last]
Open vSwitch CI c49a4a
+ * and return the corresponding file descriptor. Return -EINVAL means the
Open vSwitch CI c49a4a
+ * IOVA region doesn't exist. Caller should set start and last fields.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+#define VDUSE_IOTLB_GET_FD	_IOWR(VDUSE_BASE, 0x10, struct vduse_iotlb_entry)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/*
Open vSwitch CI c49a4a
+ * Get the negotiated virtio features. It's a subset of the features in
Open vSwitch CI c49a4a
+ * struct vduse_dev_config which can be accepted by virtio driver. It's
Open vSwitch CI c49a4a
+ * only valid after FEATURES_OK status bit is set.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+#define VDUSE_DEV_GET_FEATURES	_IOR(VDUSE_BASE, 0x11, __u64)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_config_data - data used to update configuration space
Open vSwitch CI c49a4a
+ * @offset: the offset from the beginning of configuration space
Open vSwitch CI c49a4a
+ * @length: the length to write to configuration space
Open vSwitch CI c49a4a
+ * @buffer: the buffer used to write from
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by VDUSE_DEV_SET_CONFIG ioctl to update device
Open vSwitch CI c49a4a
+ * configuration space.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_config_data {
Open vSwitch CI c49a4a
+	__u32 offset;
Open vSwitch CI c49a4a
+	__u32 length;
Open vSwitch CI c49a4a
+	__u8 buffer[];
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/* Set device configuration space */
Open vSwitch CI c49a4a
+#define VDUSE_DEV_SET_CONFIG	_IOW(VDUSE_BASE, 0x12, struct vduse_config_data)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/*
Open vSwitch CI c49a4a
+ * Inject a config interrupt. It's usually used to notify virtio driver
Open vSwitch CI c49a4a
+ * that device configuration space has changed.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+#define VDUSE_DEV_INJECT_CONFIG_IRQ	_IO(VDUSE_BASE, 0x13)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_vq_config - basic configuration of a virtqueue
Open vSwitch CI c49a4a
+ * @index: virtqueue index
Open vSwitch CI c49a4a
+ * @max_size: the max size of virtqueue
Open vSwitch CI c49a4a
+ * @reserved: for future use, needs to be initialized to zero
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by VDUSE_VQ_SETUP ioctl to setup a virtqueue.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_vq_config {
Open vSwitch CI c49a4a
+	__u32 index;
Open vSwitch CI c49a4a
+	__u16 max_size;
Open vSwitch CI c49a4a
+	__u16 reserved[13];
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/*
Open vSwitch CI c49a4a
+ * Setup the specified virtqueue. Make sure all virtqueues have been
Open vSwitch CI c49a4a
+ * configured before the device is attached to vDPA bus.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+#define VDUSE_VQ_SETUP		_IOW(VDUSE_BASE, 0x14, struct vduse_vq_config)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_vq_state_split - split virtqueue state
Open vSwitch CI c49a4a
+ * @avail_index: available index
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_vq_state_split {
Open vSwitch CI c49a4a
+	__u16 avail_index;
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_vq_state_packed - packed virtqueue state
Open vSwitch CI c49a4a
+ * @last_avail_counter: last driver ring wrap counter observed by device
Open vSwitch CI c49a4a
+ * @last_avail_idx: device available index
Open vSwitch CI c49a4a
+ * @last_used_counter: device ring wrap counter
Open vSwitch CI c49a4a
+ * @last_used_idx: used index
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_vq_state_packed {
Open vSwitch CI c49a4a
+	__u16 last_avail_counter;
Open vSwitch CI c49a4a
+	__u16 last_avail_idx;
Open vSwitch CI c49a4a
+	__u16 last_used_counter;
Open vSwitch CI c49a4a
+	__u16 last_used_idx;
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_vq_info - information of a virtqueue
Open vSwitch CI c49a4a
+ * @index: virtqueue index
Open vSwitch CI c49a4a
+ * @num: the size of virtqueue
Open vSwitch CI c49a4a
+ * @desc_addr: address of desc area
Open vSwitch CI c49a4a
+ * @driver_addr: address of driver area
Open vSwitch CI c49a4a
+ * @device_addr: address of device area
Open vSwitch CI c49a4a
+ * @split: split virtqueue state
Open vSwitch CI c49a4a
+ * @packed: packed virtqueue state
Open vSwitch CI c49a4a
+ * @ready: ready status of virtqueue
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by VDUSE_VQ_GET_INFO ioctl to get virtqueue's information.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_vq_info {
Open vSwitch CI c49a4a
+	__u32 index;
Open vSwitch CI c49a4a
+	__u32 num;
Open vSwitch CI c49a4a
+	__u64 desc_addr;
Open vSwitch CI c49a4a
+	__u64 driver_addr;
Open vSwitch CI c49a4a
+	__u64 device_addr;
Open vSwitch CI c49a4a
+	union {
Open vSwitch CI c49a4a
+		struct vduse_vq_state_split split;
Open vSwitch CI c49a4a
+		struct vduse_vq_state_packed packed;
Open vSwitch CI c49a4a
+	};
Open vSwitch CI c49a4a
+	__u8 ready;
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/* Get the specified virtqueue's information. Caller should set index field. */
Open vSwitch CI c49a4a
+#define VDUSE_VQ_GET_INFO	_IOWR(VDUSE_BASE, 0x15, struct vduse_vq_info)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_vq_eventfd - eventfd configuration for a virtqueue
Open vSwitch CI c49a4a
+ * @index: virtqueue index
Open vSwitch CI c49a4a
+ * @fd: eventfd, -1 means de-assigning the eventfd
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by VDUSE_VQ_SETUP_KICKFD ioctl to setup kick eventfd.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_vq_eventfd {
Open vSwitch CI c49a4a
+	__u32 index;
Open vSwitch CI c49a4a
+#define VDUSE_EVENTFD_DEASSIGN -1
Open vSwitch CI c49a4a
+	int fd;
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/*
Open vSwitch CI c49a4a
+ * Setup kick eventfd for specified virtqueue. The kick eventfd is used
Open vSwitch CI c49a4a
+ * by VDUSE kernel module to notify userspace to consume the avail vring.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+#define VDUSE_VQ_SETUP_KICKFD	_IOW(VDUSE_BASE, 0x16, struct vduse_vq_eventfd)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/*
Open vSwitch CI c49a4a
+ * Inject an interrupt for specific virtqueue. It's used to notify virtio driver
Open vSwitch CI c49a4a
+ * to consume the used vring.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+#define VDUSE_VQ_INJECT_IRQ	_IOW(VDUSE_BASE, 0x17, __u32)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_iova_umem - userspace memory configuration for one IOVA region
Open vSwitch CI c49a4a
+ * @uaddr: start address of userspace memory, it must be aligned to page size
Open vSwitch CI c49a4a
+ * @iova: start of the IOVA region
Open vSwitch CI c49a4a
+ * @size: size of the IOVA region
Open vSwitch CI c49a4a
+ * @reserved: for future use, needs to be initialized to zero
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by VDUSE_IOTLB_REG_UMEM and VDUSE_IOTLB_DEREG_UMEM
Open vSwitch CI c49a4a
+ * ioctls to register/de-register userspace memory for IOVA regions
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_iova_umem {
Open vSwitch CI c49a4a
+	__u64 uaddr;
Open vSwitch CI c49a4a
+	__u64 iova;
Open vSwitch CI c49a4a
+	__u64 size;
Open vSwitch CI c49a4a
+	__u64 reserved[3];
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/* Register userspace memory for IOVA regions */
Open vSwitch CI c49a4a
+#define VDUSE_IOTLB_REG_UMEM	_IOW(VDUSE_BASE, 0x18, struct vduse_iova_umem)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/* De-register the userspace memory. Caller should set iova and size field. */
Open vSwitch CI c49a4a
+#define VDUSE_IOTLB_DEREG_UMEM	_IOW(VDUSE_BASE, 0x19, struct vduse_iova_umem)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_iova_info - information of one IOVA region
Open vSwitch CI c49a4a
+ * @start: start of the IOVA region
Open vSwitch CI c49a4a
+ * @last: last of the IOVA region
Open vSwitch CI c49a4a
+ * @capability: capability of the IOVA regsion
Open vSwitch CI c49a4a
+ * @reserved: for future use, needs to be initialized to zero
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by VDUSE_IOTLB_GET_INFO ioctl to get information of
Open vSwitch CI c49a4a
+ * one IOVA region.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_iova_info {
Open vSwitch CI c49a4a
+	__u64 start;
Open vSwitch CI c49a4a
+	__u64 last;
Open vSwitch CI c49a4a
+#define VDUSE_IOVA_CAP_UMEM (1 << 0)
Open vSwitch CI c49a4a
+	__u64 capability;
Open vSwitch CI c49a4a
+	__u64 reserved[3];
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/*
Open vSwitch CI c49a4a
+ * Find the first IOVA region that overlaps with the range [start, last]
Open vSwitch CI c49a4a
+ * and return some information on it. Caller should set start and last fields.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+#define VDUSE_IOTLB_GET_INFO	_IOWR(VDUSE_BASE, 0x1a, struct vduse_iova_info)
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/* The control messages definition for read(2)/write(2) on /dev/vduse/$NAME */
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * enum vduse_req_type - request type
Open vSwitch CI c49a4a
+ * @VDUSE_GET_VQ_STATE: get the state for specified virtqueue from userspace
Open vSwitch CI c49a4a
+ * @VDUSE_SET_STATUS: set the device status
Open vSwitch CI c49a4a
+ * @VDUSE_UPDATE_IOTLB: Notify userspace to update the memory mapping for
Open vSwitch CI c49a4a
+ *                      specified IOVA range via VDUSE_IOTLB_GET_FD ioctl
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+enum vduse_req_type {
Open vSwitch CI c49a4a
+	VDUSE_GET_VQ_STATE,
Open vSwitch CI c49a4a
+	VDUSE_SET_STATUS,
Open vSwitch CI c49a4a
+	VDUSE_UPDATE_IOTLB,
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_vq_state - virtqueue state
Open vSwitch CI c49a4a
+ * @index: virtqueue index
Open vSwitch CI c49a4a
+ * @split: split virtqueue state
Open vSwitch CI c49a4a
+ * @packed: packed virtqueue state
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_vq_state {
Open vSwitch CI c49a4a
+	__u32 index;
Open vSwitch CI c49a4a
+	union {
Open vSwitch CI c49a4a
+		struct vduse_vq_state_split split;
Open vSwitch CI c49a4a
+		struct vduse_vq_state_packed packed;
Open vSwitch CI c49a4a
+	};
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_dev_status - device status
Open vSwitch CI c49a4a
+ * @status: device status
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_dev_status {
Open vSwitch CI c49a4a
+	__u8 status;
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_iova_range - IOVA range [start, last]
Open vSwitch CI c49a4a
+ * @start: start of the IOVA range
Open vSwitch CI c49a4a
+ * @last: last of the IOVA range
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_iova_range {
Open vSwitch CI c49a4a
+	__u64 start;
Open vSwitch CI c49a4a
+	__u64 last;
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_dev_request - control request
Open vSwitch CI c49a4a
+ * @type: request type
Open vSwitch CI c49a4a
+ * @request_id: request id
Open vSwitch CI c49a4a
+ * @reserved: for future use
Open vSwitch CI c49a4a
+ * @vq_state: virtqueue state, only index field is available
Open vSwitch CI c49a4a
+ * @s: device status
Open vSwitch CI c49a4a
+ * @iova: IOVA range for updating
Open vSwitch CI c49a4a
+ * @padding: padding
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by read(2) on /dev/vduse/$NAME.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_dev_request {
Open vSwitch CI c49a4a
+	__u32 type;
Open vSwitch CI c49a4a
+	__u32 request_id;
Open vSwitch CI c49a4a
+	__u32 reserved[4];
Open vSwitch CI c49a4a
+	union {
Open vSwitch CI c49a4a
+		struct vduse_vq_state vq_state;
Open vSwitch CI c49a4a
+		struct vduse_dev_status s;
Open vSwitch CI c49a4a
+		struct vduse_iova_range iova;
Open vSwitch CI c49a4a
+		__u32 padding[32];
Open vSwitch CI c49a4a
+	};
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+/**
Open vSwitch CI c49a4a
+ * struct vduse_dev_response - response to control request
Open vSwitch CI c49a4a
+ * @request_id: corresponding request id
Open vSwitch CI c49a4a
+ * @result: the result of request
Open vSwitch CI c49a4a
+ * @reserved: for future use, needs to be initialized to zero
Open vSwitch CI c49a4a
+ * @vq_state: virtqueue state
Open vSwitch CI c49a4a
+ * @padding: padding
Open vSwitch CI c49a4a
+ *
Open vSwitch CI c49a4a
+ * Structure used by write(2) on /dev/vduse/$NAME.
Open vSwitch CI c49a4a
+ */
Open vSwitch CI c49a4a
+struct vduse_dev_response {
Open vSwitch CI c49a4a
+	__u32 request_id;
Open vSwitch CI c49a4a
+#define VDUSE_REQ_RESULT_OK	0x00
Open vSwitch CI c49a4a
+#define VDUSE_REQ_RESULT_FAILED	0x01
Open vSwitch CI c49a4a
+	__u32 result;
Open vSwitch CI c49a4a
+	__u32 reserved[4];
Open vSwitch CI c49a4a
+	union {
Open vSwitch CI c49a4a
+		struct vduse_vq_state vq_state;
Open vSwitch CI c49a4a
+		__u32 padding[32];
Open vSwitch CI c49a4a
+	};
Open vSwitch CI c49a4a
+};
Open vSwitch CI c49a4a
+
Open vSwitch CI c49a4a
+#endif /* _UAPI_VDUSE_H_ */
Open vSwitch CI c49a4a
diff --git a/dpdk/lib/vhost/meson.build b/dpdk/lib/vhost/meson.build
Open vSwitch CI c49a4a
index 51bcf17244..0004f283bb 100644
Open vSwitch CI c49a4a
--- a/dpdk/lib/vhost/meson.build
Open vSwitch CI c49a4a
+++ b/dpdk/lib/vhost/meson.build
Open vSwitch CI c49a4a
@@ -26,16 +26,13 @@ sources = files(
Open vSwitch CI c49a4a
         'iotlb.c',
Open vSwitch CI c49a4a
         'socket.c',
Open vSwitch CI c49a4a
         'vdpa.c',
Open vSwitch CI c49a4a
+        'vduse.c',
Open vSwitch CI c49a4a
         'vhost.c',
Open vSwitch CI c49a4a
         'vhost_crypto.c',
Open vSwitch CI c49a4a
         'vhost_user.c',
Open vSwitch CI c49a4a
         'virtio_net.c',
Open vSwitch CI c49a4a
         'virtio_net_ctrl.c',
Open vSwitch CI c49a4a
 )
Open vSwitch CI c49a4a
-if cc.has_header('linux/vduse.h')
Open vSwitch CI c49a4a
-    sources += files('vduse.c')
Open vSwitch CI c49a4a
-    cflags += '-DVHOST_HAS_VDUSE'
Open vSwitch CI c49a4a
-endif
Open vSwitch CI c49a4a
 headers = files(
Open vSwitch CI c49a4a
         'rte_vdpa.h',
Open vSwitch CI c49a4a
         'rte_vhost.h',
Open vSwitch CI c49a4a
diff --git a/dpdk/lib/vhost/vduse.c b/dpdk/lib/vhost/vduse.c
Open vSwitch CI c49a4a
index 8ba58555f9..eaf3146b95 100644
Open vSwitch CI c49a4a
--- a/dpdk/lib/vhost/vduse.c
Open vSwitch CI c49a4a
+++ b/dpdk/lib/vhost/vduse.c
Open vSwitch CI c49a4a
@@ -8,7 +8,7 @@
Open vSwitch CI c49a4a
 #include <fcntl.h>
Open vSwitch CI c49a4a
 
Open vSwitch CI c49a4a
 
Open vSwitch CI c49a4a
-#include <linux/vduse.h>
Open vSwitch CI c49a4a
+#include <uapi/linux/vduse.h>
Open vSwitch CI c49a4a
 #include <linux/virtio_net.h>
Open vSwitch CI c49a4a
 
Open vSwitch CI c49a4a
 #include <sys/ioctl.h>
Open vSwitch CI c49a4a
diff --git a/dpdk/lib/vhost/vduse.h b/dpdk/lib/vhost/vduse.h
Open vSwitch CI c49a4a
index 0d8f3f1205..47ca97a064 100644
Open vSwitch CI c49a4a
--- a/dpdk/lib/vhost/vduse.h
Open vSwitch CI c49a4a
+++ b/dpdk/lib/vhost/vduse.h
Open vSwitch CI c49a4a
@@ -9,29 +9,7 @@
Open vSwitch CI c49a4a
 
Open vSwitch CI c49a4a
 #define VDUSE_NET_SUPPORTED_FEATURES VIRTIO_NET_SUPPORTED_FEATURES
Open vSwitch CI c49a4a
 
Open vSwitch CI c49a4a
-#ifdef VHOST_HAS_VDUSE
Open vSwitch CI c49a4a
-
Open vSwitch CI c49a4a
 int vduse_device_create(const char *path, bool compliant_ol_flags);
Open vSwitch CI c49a4a
 int vduse_device_destroy(const char *path);
Open vSwitch CI c49a4a
 
Open vSwitch CI c49a4a
-#else
Open vSwitch CI c49a4a
-
Open vSwitch CI c49a4a
-static inline int
Open vSwitch CI c49a4a
-vduse_device_create(const char *path, bool compliant_ol_flags)
Open vSwitch CI c49a4a
-{
Open vSwitch CI c49a4a
-	RTE_SET_USED(compliant_ol_flags);
Open vSwitch CI c49a4a
-
Open vSwitch CI c49a4a
-	VHOST_CONFIG_LOG(path, ERR, "VDUSE support disabled at build time");
Open vSwitch CI c49a4a
-	return -1;
Open vSwitch CI c49a4a
-}
Open vSwitch CI c49a4a
-
Open vSwitch CI c49a4a
-static inline int
Open vSwitch CI c49a4a
-vduse_device_destroy(const char *path)
Open vSwitch CI c49a4a
-{
Open vSwitch CI c49a4a
-	VHOST_CONFIG_LOG(path, ERR, "VDUSE support disabled at build time");
Open vSwitch CI c49a4a
-	return -1;
Open vSwitch CI c49a4a
-}
Open vSwitch CI c49a4a
-
Open vSwitch CI c49a4a
-#endif /* VHOST_HAS_VDUSE */
Open vSwitch CI c49a4a
-
Open vSwitch CI c49a4a
 #endif /* _VDUSE_H */
Open vSwitch CI 70cc8f
diff --git a/dpdk/lib/vhost/virtio_net.c b/dpdk/lib/vhost/virtio_net.c
Open vSwitch CI 70cc8f
index d764d4bc6a..a340e5a772 100644
Open vSwitch CI 70cc8f
--- a/dpdk/lib/vhost/virtio_net.c
Open vSwitch CI 70cc8f
+++ b/dpdk/lib/vhost/virtio_net.c
Open vSwitch CI 70cc8f
@@ -2823,6 +2823,9 @@ vhost_dequeue_offload(struct virtio_net *dev, struct virtio_net_hdr *hdr,
Open vSwitch CI 70cc8f
 			 */
Open vSwitch CI 70cc8f
 			uint16_t csum = 0, off;
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
+			if (hdr->csum_start >= rte_pktmbuf_pkt_len(m))
Open vSwitch CI 70cc8f
+				return;
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
 			if (rte_raw_cksum_mbuf(m, hdr->csum_start,
Open vSwitch CI 70cc8f
 					rte_pktmbuf_pkt_len(m) - hdr->csum_start, &csum) < 0)
Open vSwitch CI 70cc8f
 				return;
Open vSwitch CI 70cc8f
@@ -3626,6 +3629,8 @@ rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
Open vSwitch CI 70cc8f
 		rte_rwlock_read_unlock(&vq->access_lock);
Open vSwitch CI 70cc8f
 
Open vSwitch CI 70cc8f
 		virtio_dev_vring_translate(dev, vq);
Open vSwitch CI 70cc8f
+
Open vSwitch CI 70cc8f
+		count = 0;
Open vSwitch CI 70cc8f
 		goto out_no_unlock;
Open vSwitch CI 70cc8f
 	}
Open vSwitch CI 70cc8f