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