diff mbox series

[ovs-dev,v27,8/8] system-offloads-traffic.at: Add sFlow offload test cases

Message ID 20230601111658.113144-9-cmi@nvidia.com
State Changes Requested
Headers show
Series Add offload support for sFlow | expand

Checks

Context Check Description
ovsrobot/intel-ovs-compilation success test: success
ovsrobot/apply-robot warning apply and check: warning
ovsrobot/github-robot-_Build_and_Test success github build: passed

Commit Message

Chris Mi June 1, 2023, 11:16 a.m. UTC
Add three sFlow offload test cases:

  3: offloads - sflow with sampling=1 - offloads enabled ok
  4: offloads - sflow with sampling=2 - offloads enabled ok
  5: offloads - ping over vxlan tunnel with sflow - offloads enabled ok

Signed-off-by: Chris Mi <cmi@nvidia.com>
Reviewed-by: Roi Dayan <roid@nvidia.com>
Acked-by: Eelco Chaudron <echaudro@redhat.com>
---
 Documentation/howto/tc-offload.rst |  24 +++++
 tests/system-offloads-traffic.at   | 152 +++++++++++++++++++++++++++++
 2 files changed, 176 insertions(+)

Comments

Eelco Chaudron June 16, 2023, 2:27 p.m. UTC | #1
On 1 Jun 2023, at 13:16, Chris Mi wrote:

> Add three sFlow offload test cases:
>
>   3: offloads - sflow with sampling=1 - offloads enabled ok
>   4: offloads - sflow with sampling=2 - offloads enabled ok
>   5: offloads - ping over vxlan tunnel with sflow - offloads enabled ok
>
> Signed-off-by: Chris Mi <cmi@nvidia.com>
> Reviewed-by: Roi Dayan <roid@nvidia.com>
> Acked-by: Eelco Chaudron <echaudro@redhat.com>

See some comments inline below.

//Eelco

> ---
>  Documentation/howto/tc-offload.rst |  24 +++++
>  tests/system-offloads-traffic.at   | 152 +++++++++++++++++++++++++++++
>  2 files changed, 176 insertions(+)
>
> diff --git a/Documentation/howto/tc-offload.rst b/Documentation/howto/tc-offload.rst
> index 681dff13e..a50dc3c58 100644
> --- a/Documentation/howto/tc-offload.rst
> +++ b/Documentation/howto/tc-offload.rst
> @@ -88,6 +88,30 @@ As you can see above the none-offload case reports 140 bytes more, which is 14
>  bytes per packet. This represents the L2 header, in this case, 2 * *Ethernet
>  address* + *Ethertype*.
>
> +Tunnel offload
> +++++++++++++++
> +
> +Current tunnel offload ignores DF and CSUM flags configuration requested by
> +the user. TC for now has no way to pass these flags in a flower key and their
> +masks are set by default. To make tunnel offload work, DF and CSUM flags
> +are cleared. So please be aware of the following differences.
> +
> +Dumping vxlan decap match without offload, it shows::
> +
> +    recirc_id(0),tunnel(tun_id=0x4,src=192.168.1.1,dst=192.168.1.2,flags(-df+csum+key)),in_port(vxlan_sys_4789)
> +
> +Dumping vxlan decap match with offload, it shows::
> +
> +    recirc_id(0),tunnel(tun_id=0x4,src=192.168.1.1,dst=192.168.1.2,tp_dst=4789,flags(+key)),in_port(vxlan_sys_4789)
> +
> +Dumping vxlan encap action without offload, it shows::
> +
> +    actions:set(tunnel(tun_id=0x4,dst=192.168.1.1,ttl=64,tp_dst=4789,flags(df|key))),vxlan_sys_4789
> +
> +Dumping vxlan encap action with offload, it shows::
> +
> +    actions:set(tunnel(tun_id=0x4,dst=192.168.1.64,ttl=64,tp_dst=4789,flags(key))),vxlan_sys_4789
> +
>  TC Meter Offload
>  ~~~~~~~~~~~~~~~~
>
> diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at
> index ae302a294..0704ea491 100644
> --- a/tests/system-offloads-traffic.at
> +++ b/tests/system-offloads-traffic.at
> @@ -93,6 +93,158 @@ AT_CHECK([ovs-appctl upcall/show | grep -E "offloaded flows : [[1-9]]"], [0], [i
>  OVS_TRAFFIC_VSWITCHD_STOP
>  AT_CLEANUP

If the psample module is not loaded all these tests fail. Guess we can do the same as OVN, and add the LOAD_MODULE macro.

> +
> +AT_SETUP([offloads - sflow with sampling=1 - offloads enabled])
> +OVS_TRAFFIC_VSWITCHD_START([], [], [-- set Open_vSwitch . other_config:hw-offload=true])
> +
> +on_exit 'kill `cat test-sflow.pid`'
> +AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
> +AT_CAPTURE_FILE([sflow.log])
> +PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
> +
> +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
> +
> +ADD_NAMESPACES(at_ns0, at_ns1)
> +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> +
> +AT_CHECK([ovs-vsctl -- --id=@sflow create sflow agent=lo target=\"127.0.0.1:$SFLOW_PORT\" header=128 sampling=1 polling=100 -- set bridge br0 sflow=@sflow], [0], [ignore])
> +NS_CHECK_EXEC([at_ns0], [ping -q -c 1000 -i 0.01 -w 12 10.1.1.2 | FORMAT_PING], [0], [dnl
> +1000 packets transmitted, 1000 received, 0% packet loss, time 0ms
> +])
> +
> +p1_ifindex=$(cat /sys/class/net/ovs-p1/ifindex)
> +m4_define([DUMP_SFLOW], [sed -e "s/used:[[0-9]].[[0-9]]*s/used:0.001s/;s/eth(src=[[a-z0-9:]]*,dst=[[a-z0-9:]]*)/eth(macs)/;s/pid=[[0-9]]*/pid=1/;s/output=$p1_ifindex/output=1/"])
> +AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "in_port(2)" | grep "eth_type(0x0800)" | grep "actions:userspace" | grep "sFlow" | DUMP_SFLOW], [0], [dnl
> +recirc_id(0),in_port(2),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:83916, used:0.001s, actions:userspace(pid=1,sFlow(vid=0,pcp=0,output=1),actions),3
> +])
> +
> +p0_ifindex=$(cat /sys/class/net/ovs-p0/ifindex)
> +m4_define([DUMP_SFLOW], [sed -e "s/used:[[0-9]].[[0-9]]*s/used:0.001s/;s/eth(src=[[a-z0-9:]]*,dst=[[a-z0-9:]]*)/eth(macs)/;s/pid=[[0-9]]*/pid=1/;s/output=$p0_ifindex/output=1/"])
> +AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "in_port(3)" | grep "eth_type(0x0800)" | grep "actions:userspace" | grep "sFlow" | DUMP_SFLOW], [0], [dnl
> +recirc_id(0),in_port(3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:83916, used:0.001s, actions:userspace(pid=1,sFlow(vid=0,pcp=0,output=1),actions),2
> +])
> +
> +hdr="in_ifindex=$p0_ifindex in_format=0 out_ifindex=$p1_ifindex out_format=0 hdr_prot=1 pkt_len=102 stripped=4 hdr_len=98"
> +count=`grep "$hdr" sflow.log | wc -l`
> +AT_CHECK([[[[ $count -ge 996 ]]]])
> +hdr="in_ifindex=$p1_ifindex in_format=0 out_ifindex=$p0_ifindex out_format=0 hdr_prot=1 pkt_len=102 stripped=4 hdr_len=98"
> +count=`grep "$hdr" sflow.log | wc -l`
> +AT_CHECK([[[[ $count -ge 996 ]]]])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP
> +OVS_APP_EXIT_AND_WAIT([test-sflow])
> +AT_CLEANUP
> +
> +
> +AT_SETUP([offloads - sflow with sampling=2 - offloads enabled])
> +OVS_TRAFFIC_VSWITCHD_START([], [], [-- set Open_vSwitch . other_config:hw-offload=true])
> +
> +on_exit 'kill `cat test-sflow.pid`'
> +AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
> +AT_CAPTURE_FILE([sflow.log])
> +PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
> +
> +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
> +
> +ADD_NAMESPACES(at_ns0, at_ns1)
> +ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
> +ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
> +
> +AT_CHECK([ovs-vsctl -- --id=@sflow create sflow agent=lo target=\"127.0.0.1:$SFLOW_PORT\" header=128 sampling=2 polling=100 -- set bridge br0 sflow=@sflow], [0], [ignore])
> +NS_CHECK_EXEC([at_ns0], [ping -q -c 1000 -i 0.01 -w 12 10.1.1.2 | FORMAT_PING], [0], [dnl
> +1000 packets transmitted, 1000 received, 0% packet loss, time 0ms
> +])
> +
> +p1_ifindex=$(cat /sys/class/net/ovs-p1/ifindex)
> +m4_define([DUMP_SFLOW], [sed -e "s/used:[[0-9]].[[0-9]]*s/used:0.001s/;s/eth(src=[[a-z0-9:]]*,dst=[[a-z0-9:]]*)/eth(macs)/;s/pid=[[0-9]]*/pid=1/;s/output=$p1_ifindex/output=1/"])
> +AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "in_port(2)" | grep "eth_type(0x0800)" | grep "actions:sample" | grep "sFlow" | DUMP_SFLOW], [0], [dnl
> +recirc_id(0),in_port(2),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:83916, used:0.001s, actions:sample(sample=50.0%,actions(userspace(pid=1,sFlow(vid=0,pcp=0,output=1),actions))),3
> +])
> +
> +p0_ifindex=$(cat /sys/class/net/ovs-p0/ifindex)
> +m4_define([DUMP_SFLOW], [sed -e "s/used:[[0-9]].[[0-9]]*s/used:0.001s/;s/eth(src=[[a-z0-9:]]*,dst=[[a-z0-9:]]*)/eth(macs)/;s/pid=[[0-9]]*/pid=1/;s/output=$p0_ifindex/output=1/"])
> +AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "in_port(3)" | grep "eth_type(0x0800)" | grep "actions:sample" | grep "sFlow" | DUMP_SFLOW], [0], [dnl
> +recirc_id(0),in_port(3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:83916, used:0.001s, actions:sample(sample=50.0%,actions(userspace(pid=1,sFlow(vid=0,pcp=0,output=1),actions))),2
> +])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP
> +OVS_APP_EXIT_AND_WAIT([test-sflow])
> +count=`cat sflow.log | wc -l`
> +AT_CHECK([[[[ $count -le 1100 && $count -ge 900 ]]]])

Here you only test the amount, not on the ifindex as with the previous test.
Also the location is different, above you do this before OVS_TRAFFIC_VSWITCHD_STOP.

> +AT_CLEANUP
> +
> +
> +AT_SETUP([offloads - ping over vxlan tunnel with sflow - offloads enabled])
> +OVS_CHECK_TUNNEL_TSO()
> +OVS_CHECK_VXLAN()
> +
> +OVS_TRAFFIC_VSWITCHD_START([], [], [-- set Open_vSwitch . other_config:hw-offload=true])
> +ADD_BR([br-underlay])
> +
> +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
> +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
> +
> +ADD_NAMESPACES(at_ns0)
> +
> +dnl Set up underlay link from host into the namespace using veth pair.
> +ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24")
> +AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
> +AT_CHECK([ip link set dev br-underlay up])
> +
> +dnl Set up tunnel endpoints on OVS outside the namespace and with a native
> +dnl linux device inside the namespace.
> +ADD_OVS_TUNNEL([vxlan], [br0], [at_vxlan0], [172.31.1.1], [10.1.1.100/24])
> +ADD_NATIVE_TUNNEL([vxlan], [at_vxlan1], [at_ns0], [172.31.1.100], [10.1.1.1/24],
> +                  [id 0 dstport 4789])
> +
> +on_exit 'kill `cat test-sflow.pid`'
> +AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
> +AT_CAPTURE_FILE([sflow.log])
> +PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
> +AT_CHECK([ovs-vsctl -- --id=@sflow create sflow agent=lo target=\"127.0.0.1:$SFLOW_PORT\" header=128 sampling=1 polling=100 -- set bridge br0 sflow=@sflow], [0], [ignore])
> +
> +dnl First, check the underlay

Make sure all comments end with a dot.

> +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], [0], [dnl
> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
> +])
> +
> +dnl Okay, now check the overlay
> +NS_CHECK_EXEC([at_ns0], [ping -q -c 1000 -i 0.01 10.1.1.100 | FORMAT_PING], [0], [dnl
> +1000 packets transmitted, 1000 received, 0% packet loss, time 0ms
> +])
> +
> +vxlan_sys_ifindex=$(cat /sys/class/net/vxlan_sys_4789/ifindex)
> +br0_ifindex=$(cat /sys/class/net/br0/ifindex)
> +br0_mac=$(cat /sys/class/net/br0/address)
> +vxlan1_mac=$(ip netns exec at_ns0 cat /sys/class/net/at_vxlan1/address)
> +
> +dnl Check encap flow
> +match="recirc_id(0),in_port(br0),eth(src=$br0_mac,dst=$vxlan1_mac),eth_type(0x0800),ipv4(tos=0/0x3,frag=no)"
> +action="actions:userspace(pid=4294967295,sFlow(vid=0,pcp=0,output=$vxlan_sys_ifindex),actions),set(tunnel(dst=172.31.1.1,ttl=64,tp_dst=4789,flags(0))),vxlan_sys_4789"
> +AT_CHECK([ovs-appctl dpctl/dump-flows --names | grep $match | grep $action > /dev/null])
> +
> +dnl Check decap flow
> +match="recirc_id(0),tunnel(tun_id=0x0,src=172.31.1.1,dst=172.31.1.100,tp_dst=4789,flags(+key)),in_port(vxlan_sys_4789),eth(src=$vxlan1_mac,dst=$br0_mac),eth_type(0x0800),ipv4(frag=no)"
> +action="actions:userspace(pid=4294967295,sFlow(vid=0,pcp=0,output=$br0_ifindex),actions),br0"
> +AT_CHECK([ovs-appctl dpctl/dump-flows --names | grep $match | grep $action> /dev/null])
> +
> +dnl Vni is 0, test-sflow doesn't show it
> +out_tunnel_hdr="tunnel4_out_protocol=17 tunnel4_out_src=0.0.0.0 tunnel4_out_dst=172.31.1.1 tunnel4_out_src_port=0 tunnel4_out_dst_port=46354"
> +ifindex="in_ifindex=$br0_ifindex in_format=0 out_ifindex=$vxlan_sys_ifindex"
> +out_count=`grep "$out_tunnel_hdr" sflow.log | grep "$ifindex" | wc -l`
> +AT_CHECK([[[[ $out_count -ge 999 ]]]])
> +
> +in_tunnel_hdr="tunnel4_in_protocol=17 tunnel4_in_src=172.31.1.1 tunnel4_in_dst=172.31.1.100"
> +ifindex="in_ifindex=$vxlan_sys_ifindex in_format=0 out_ifindex=$br0_ifindex"
> +in_count=`grep "$in_tunnel_hdr" sflow.log | grep "$ifindex" | wc -l`
> +AT_CHECK([[[[ $in_count -ge 999 ]]]])
> +
> +OVS_TRAFFIC_VSWITCHD_STOP
> +OVS_APP_EXIT_AND_WAIT([test-sflow])
> +AT_CLEANUP
> +
> +
>  AT_SETUP([offloads - set ingress_policing_rate and ingress_policing_burst - offloads disabled])
>  AT_KEYWORDS([ingress_policing])
>  AT_SKIP_IF([test $HAVE_TC = "no"])
> -- 
> 2.26.3

Here is a full diff of the suggested changes, if you sent a v28 with only these changes I can ack the patch:

diff --git a/tests/system-common-macros.at b/tests/system-common-macros.at
index 0077a8609..55ec0bf1e 100644
--- a/tests/system-common-macros.at
+++ b/tests/system-common-macros.at
@@ -359,3 +359,16 @@ m4_define([OVS_CHECK_IPROUTE_ENCAP],
 # OVS_CHECK_CT_CLEAR()
 m4_define([OVS_CHECK_CT_CLEAR],
     [AT_SKIP_IF([! grep -q "Datapath supports ct_clear action" ovs-vswitchd.log])])
+
+# LOAD_MODULE([name])
+#
+# Tries to load specified kernel module and removes it after
+# if it wasn't loaded before this call.
+#
+m4_define([LOAD_MODULE],
+    [if ! lsmod | grep -q $1; then
+         on_exit 'modprobe -q -r $1'
+     fi
+     AT_CHECK([modprobe $1])
+    ]
+)
\ No newline at end of file
diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at
index 0704ea491..db287a86d 100644
--- a/tests/system-offloads-traffic.at
+++ b/tests/system-offloads-traffic.at
@@ -95,6 +95,7 @@ AT_CLEANUP


 AT_SETUP([offloads - sflow with sampling=1 - offloads enabled])
+LOAD_MODULE([psample])
 OVS_TRAFFIC_VSWITCHD_START([], [], [-- set Open_vSwitch . other_config:hw-offload=true])

 on_exit 'kill `cat test-sflow.pid`'
@@ -138,6 +139,7 @@ AT_CLEANUP


 AT_SETUP([offloads - sflow with sampling=2 - offloads enabled])
+LOAD_MODULE([psample])
 OVS_TRAFFIC_VSWITCHD_START([], [], [-- set Open_vSwitch . other_config:hw-offload=true])

 on_exit 'kill `cat test-sflow.pid`'
@@ -168,16 +170,22 @@ AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "in_port(3)" | gr
 recirc_id(0),in_port(3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:83916, used:0.001s, actions:sample(sample=50.0%,actions(userspace(pid=1,sFlow(vid=0,pcp=0,output=1),actions))),2
 ])

+hdr="in_ifindex=$p0_ifindex in_format=0 out_ifindex=$p1_ifindex out_format=0 hdr_prot=1 pkt_len=102 stripped=4 hdr_len=98"
+count=`grep "$hdr" sflow.log | wc -l`
+AT_CHECK([[[[ $count -le 550 && $count -ge 450 ]]]])
+hdr="in_ifindex=$p1_ifindex in_format=0 out_ifindex=$p0_ifindex out_format=0 hdr_prot=1 pkt_len=102 stripped=4 hdr_len=98"
+count=`grep "$hdr" sflow.log | wc -l`
+AT_CHECK([[[[ $count -le 550 && $count -ge 450 ]]]])
+
 OVS_TRAFFIC_VSWITCHD_STOP
 OVS_APP_EXIT_AND_WAIT([test-sflow])
-count=`cat sflow.log | wc -l`
-AT_CHECK([[[[ $count -le 1100 && $count -ge 900 ]]]])
 AT_CLEANUP


 AT_SETUP([offloads - ping over vxlan tunnel with sflow - offloads enabled])
 OVS_CHECK_TUNNEL_TSO()
 OVS_CHECK_VXLAN()
+LOAD_MODULE([psample])

 OVS_TRAFFIC_VSWITCHD_START([], [], [-- set Open_vSwitch . other_config:hw-offload=true])
 ADD_BR([br-underlay])
@@ -204,12 +212,12 @@ AT_CAPTURE_FILE([sflow.log])
 PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
 AT_CHECK([ovs-vsctl -- --id=@sflow create sflow agent=lo target=\"127.0.0.1:$SFLOW_PORT\" header=128 sampling=1 polling=100 -- set bridge br0 sflow=@sflow], [0], [ignore])

-dnl First, check the underlay
+dnl First, check the underlay.
 NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], [0], [dnl
 3 packets transmitted, 3 received, 0% packet loss, time 0ms
 ])

-dnl Okay, now check the overlay
+dnl Okay, now check the overlay.
 NS_CHECK_EXEC([at_ns0], [ping -q -c 1000 -i 0.01 10.1.1.100 | FORMAT_PING], [0], [dnl
 1000 packets transmitted, 1000 received, 0% packet loss, time 0ms
 ])
@@ -219,17 +227,17 @@ br0_ifindex=$(cat /sys/class/net/br0/ifindex)
 br0_mac=$(cat /sys/class/net/br0/address)
 vxlan1_mac=$(ip netns exec at_ns0 cat /sys/class/net/at_vxlan1/address)

-dnl Check encap flow
+dnl Check the encap flow.
 match="recirc_id(0),in_port(br0),eth(src=$br0_mac,dst=$vxlan1_mac),eth_type(0x0800),ipv4(tos=0/0x3,frag=no)"
 action="actions:userspace(pid=4294967295,sFlow(vid=0,pcp=0,output=$vxlan_sys_ifindex),actions),set(tunnel(dst=172.31.1.1,ttl=64,tp_dst=4789,flags(0))),vxlan_sys_4789"
 AT_CHECK([ovs-appctl dpctl/dump-flows --names | grep $match | grep $action > /dev/null])

-dnl Check decap flow
+dnl Check the decap flow.
 match="recirc_id(0),tunnel(tun_id=0x0,src=172.31.1.1,dst=172.31.1.100,tp_dst=4789,flags(+key)),in_port(vxlan_sys_4789),eth(src=$vxlan1_mac,dst=$br0_mac),eth_type(0x0800),ipv4(frag=no)"
 action="actions:userspace(pid=4294967295,sFlow(vid=0,pcp=0,output=$br0_ifindex),actions),br0"
 AT_CHECK([ovs-appctl dpctl/dump-flows --names | grep $match | grep $action> /dev/null])

-dnl Vni is 0, test-sflow doesn't show it
+dnl Vni is 0, test-sflow doesn't show it.
 out_tunnel_hdr="tunnel4_out_protocol=17 tunnel4_out_src=0.0.0.0 tunnel4_out_dst=172.31.1.1 tunnel4_out_src_port=0 tunnel4_out_dst_port=46354"
 ifindex="in_ifindex=$br0_ifindex in_format=0 out_ifindex=$vxlan_sys_ifindex"
 out_count=`grep "$out_tunnel_hdr" sflow.log | grep "$ifindex" | wc -l`
diff mbox series

Patch

diff --git a/Documentation/howto/tc-offload.rst b/Documentation/howto/tc-offload.rst
index 681dff13e..a50dc3c58 100644
--- a/Documentation/howto/tc-offload.rst
+++ b/Documentation/howto/tc-offload.rst
@@ -88,6 +88,30 @@  As you can see above the none-offload case reports 140 bytes more, which is 14
 bytes per packet. This represents the L2 header, in this case, 2 * *Ethernet
 address* + *Ethertype*.
 
+Tunnel offload
+++++++++++++++
+
+Current tunnel offload ignores DF and CSUM flags configuration requested by
+the user. TC for now has no way to pass these flags in a flower key and their
+masks are set by default. To make tunnel offload work, DF and CSUM flags
+are cleared. So please be aware of the following differences.
+
+Dumping vxlan decap match without offload, it shows::
+
+    recirc_id(0),tunnel(tun_id=0x4,src=192.168.1.1,dst=192.168.1.2,flags(-df+csum+key)),in_port(vxlan_sys_4789)
+
+Dumping vxlan decap match with offload, it shows::
+
+    recirc_id(0),tunnel(tun_id=0x4,src=192.168.1.1,dst=192.168.1.2,tp_dst=4789,flags(+key)),in_port(vxlan_sys_4789)
+
+Dumping vxlan encap action without offload, it shows::
+
+    actions:set(tunnel(tun_id=0x4,dst=192.168.1.1,ttl=64,tp_dst=4789,flags(df|key))),vxlan_sys_4789
+
+Dumping vxlan encap action with offload, it shows::
+
+    actions:set(tunnel(tun_id=0x4,dst=192.168.1.64,ttl=64,tp_dst=4789,flags(key))),vxlan_sys_4789
+
 TC Meter Offload
 ~~~~~~~~~~~~~~~~
 
diff --git a/tests/system-offloads-traffic.at b/tests/system-offloads-traffic.at
index ae302a294..0704ea491 100644
--- a/tests/system-offloads-traffic.at
+++ b/tests/system-offloads-traffic.at
@@ -93,6 +93,158 @@  AT_CHECK([ovs-appctl upcall/show | grep -E "offloaded flows : [[1-9]]"], [0], [i
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+
+AT_SETUP([offloads - sflow with sampling=1 - offloads enabled])
+OVS_TRAFFIC_VSWITCHD_START([], [], [-- set Open_vSwitch . other_config:hw-offload=true])
+
+on_exit 'kill `cat test-sflow.pid`'
+AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
+AT_CAPTURE_FILE([sflow.log])
+PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
+
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+AT_CHECK([ovs-vsctl -- --id=@sflow create sflow agent=lo target=\"127.0.0.1:$SFLOW_PORT\" header=128 sampling=1 polling=100 -- set bridge br0 sflow=@sflow], [0], [ignore])
+NS_CHECK_EXEC([at_ns0], [ping -q -c 1000 -i 0.01 -w 12 10.1.1.2 | FORMAT_PING], [0], [dnl
+1000 packets transmitted, 1000 received, 0% packet loss, time 0ms
+])
+
+p1_ifindex=$(cat /sys/class/net/ovs-p1/ifindex)
+m4_define([DUMP_SFLOW], [sed -e "s/used:[[0-9]].[[0-9]]*s/used:0.001s/;s/eth(src=[[a-z0-9:]]*,dst=[[a-z0-9:]]*)/eth(macs)/;s/pid=[[0-9]]*/pid=1/;s/output=$p1_ifindex/output=1/"])
+AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "in_port(2)" | grep "eth_type(0x0800)" | grep "actions:userspace" | grep "sFlow" | DUMP_SFLOW], [0], [dnl
+recirc_id(0),in_port(2),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:83916, used:0.001s, actions:userspace(pid=1,sFlow(vid=0,pcp=0,output=1),actions),3
+])
+
+p0_ifindex=$(cat /sys/class/net/ovs-p0/ifindex)
+m4_define([DUMP_SFLOW], [sed -e "s/used:[[0-9]].[[0-9]]*s/used:0.001s/;s/eth(src=[[a-z0-9:]]*,dst=[[a-z0-9:]]*)/eth(macs)/;s/pid=[[0-9]]*/pid=1/;s/output=$p0_ifindex/output=1/"])
+AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "in_port(3)" | grep "eth_type(0x0800)" | grep "actions:userspace" | grep "sFlow" | DUMP_SFLOW], [0], [dnl
+recirc_id(0),in_port(3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:83916, used:0.001s, actions:userspace(pid=1,sFlow(vid=0,pcp=0,output=1),actions),2
+])
+
+hdr="in_ifindex=$p0_ifindex in_format=0 out_ifindex=$p1_ifindex out_format=0 hdr_prot=1 pkt_len=102 stripped=4 hdr_len=98"
+count=`grep "$hdr" sflow.log | wc -l`
+AT_CHECK([[[[ $count -ge 996 ]]]])
+hdr="in_ifindex=$p1_ifindex in_format=0 out_ifindex=$p0_ifindex out_format=0 hdr_prot=1 pkt_len=102 stripped=4 hdr_len=98"
+count=`grep "$hdr" sflow.log | wc -l`
+AT_CHECK([[[[ $count -ge 996 ]]]])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+OVS_APP_EXIT_AND_WAIT([test-sflow])
+AT_CLEANUP
+
+
+AT_SETUP([offloads - sflow with sampling=2 - offloads enabled])
+OVS_TRAFFIC_VSWITCHD_START([], [], [-- set Open_vSwitch . other_config:hw-offload=true])
+
+on_exit 'kill `cat test-sflow.pid`'
+AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
+AT_CAPTURE_FILE([sflow.log])
+PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
+
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
+
+ADD_NAMESPACES(at_ns0, at_ns1)
+ADD_VETH(p0, at_ns0, br0, "10.1.1.1/24")
+ADD_VETH(p1, at_ns1, br0, "10.1.1.2/24")
+
+AT_CHECK([ovs-vsctl -- --id=@sflow create sflow agent=lo target=\"127.0.0.1:$SFLOW_PORT\" header=128 sampling=2 polling=100 -- set bridge br0 sflow=@sflow], [0], [ignore])
+NS_CHECK_EXEC([at_ns0], [ping -q -c 1000 -i 0.01 -w 12 10.1.1.2 | FORMAT_PING], [0], [dnl
+1000 packets transmitted, 1000 received, 0% packet loss, time 0ms
+])
+
+p1_ifindex=$(cat /sys/class/net/ovs-p1/ifindex)
+m4_define([DUMP_SFLOW], [sed -e "s/used:[[0-9]].[[0-9]]*s/used:0.001s/;s/eth(src=[[a-z0-9:]]*,dst=[[a-z0-9:]]*)/eth(macs)/;s/pid=[[0-9]]*/pid=1/;s/output=$p1_ifindex/output=1/"])
+AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "in_port(2)" | grep "eth_type(0x0800)" | grep "actions:sample" | grep "sFlow" | DUMP_SFLOW], [0], [dnl
+recirc_id(0),in_port(2),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:83916, used:0.001s, actions:sample(sample=50.0%,actions(userspace(pid=1,sFlow(vid=0,pcp=0,output=1),actions))),3
+])
+
+p0_ifindex=$(cat /sys/class/net/ovs-p0/ifindex)
+m4_define([DUMP_SFLOW], [sed -e "s/used:[[0-9]].[[0-9]]*s/used:0.001s/;s/eth(src=[[a-z0-9:]]*,dst=[[a-z0-9:]]*)/eth(macs)/;s/pid=[[0-9]]*/pid=1/;s/output=$p0_ifindex/output=1/"])
+AT_CHECK([ovs-appctl dpctl/dump-flows type=tc,offloaded | grep "in_port(3)" | grep "eth_type(0x0800)" | grep "actions:sample" | grep "sFlow" | DUMP_SFLOW], [0], [dnl
+recirc_id(0),in_port(3),eth(macs),eth_type(0x0800),ipv4(frag=no), packets:999, bytes:83916, used:0.001s, actions:sample(sample=50.0%,actions(userspace(pid=1,sFlow(vid=0,pcp=0,output=1),actions))),2
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+OVS_APP_EXIT_AND_WAIT([test-sflow])
+count=`cat sflow.log | wc -l`
+AT_CHECK([[[[ $count -le 1100 && $count -ge 900 ]]]])
+AT_CLEANUP
+
+
+AT_SETUP([offloads - ping over vxlan tunnel with sflow - offloads enabled])
+OVS_CHECK_TUNNEL_TSO()
+OVS_CHECK_VXLAN()
+
+OVS_TRAFFIC_VSWITCHD_START([], [], [-- set Open_vSwitch . other_config:hw-offload=true])
+ADD_BR([br-underlay])
+
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
+
+ADD_NAMESPACES(at_ns0)
+
+dnl Set up underlay link from host into the namespace using veth pair.
+ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24")
+AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
+AT_CHECK([ip link set dev br-underlay up])
+
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
+dnl linux device inside the namespace.
+ADD_OVS_TUNNEL([vxlan], [br0], [at_vxlan0], [172.31.1.1], [10.1.1.100/24])
+ADD_NATIVE_TUNNEL([vxlan], [at_vxlan1], [at_ns0], [172.31.1.100], [10.1.1.1/24],
+                  [id 0 dstport 4789])
+
+on_exit 'kill `cat test-sflow.pid`'
+AT_CHECK([ovstest test-sflow --log-file --detach --no-chdir --pidfile 0:127.0.0.1 > sflow.log], [0], [], [ignore])
+AT_CAPTURE_FILE([sflow.log])
+PARSE_LISTENING_PORT([test-sflow.log], [SFLOW_PORT])
+AT_CHECK([ovs-vsctl -- --id=@sflow create sflow agent=lo target=\"127.0.0.1:$SFLOW_PORT\" header=128 sampling=1 polling=100 -- set bridge br0 sflow=@sflow], [0], [ignore])
+
+dnl First, check the underlay
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl Okay, now check the overlay
+NS_CHECK_EXEC([at_ns0], [ping -q -c 1000 -i 0.01 10.1.1.100 | FORMAT_PING], [0], [dnl
+1000 packets transmitted, 1000 received, 0% packet loss, time 0ms
+])
+
+vxlan_sys_ifindex=$(cat /sys/class/net/vxlan_sys_4789/ifindex)
+br0_ifindex=$(cat /sys/class/net/br0/ifindex)
+br0_mac=$(cat /sys/class/net/br0/address)
+vxlan1_mac=$(ip netns exec at_ns0 cat /sys/class/net/at_vxlan1/address)
+
+dnl Check encap flow
+match="recirc_id(0),in_port(br0),eth(src=$br0_mac,dst=$vxlan1_mac),eth_type(0x0800),ipv4(tos=0/0x3,frag=no)"
+action="actions:userspace(pid=4294967295,sFlow(vid=0,pcp=0,output=$vxlan_sys_ifindex),actions),set(tunnel(dst=172.31.1.1,ttl=64,tp_dst=4789,flags(0))),vxlan_sys_4789"
+AT_CHECK([ovs-appctl dpctl/dump-flows --names | grep $match | grep $action > /dev/null])
+
+dnl Check decap flow
+match="recirc_id(0),tunnel(tun_id=0x0,src=172.31.1.1,dst=172.31.1.100,tp_dst=4789,flags(+key)),in_port(vxlan_sys_4789),eth(src=$vxlan1_mac,dst=$br0_mac),eth_type(0x0800),ipv4(frag=no)"
+action="actions:userspace(pid=4294967295,sFlow(vid=0,pcp=0,output=$br0_ifindex),actions),br0"
+AT_CHECK([ovs-appctl dpctl/dump-flows --names | grep $match | grep $action> /dev/null])
+
+dnl Vni is 0, test-sflow doesn't show it
+out_tunnel_hdr="tunnel4_out_protocol=17 tunnel4_out_src=0.0.0.0 tunnel4_out_dst=172.31.1.1 tunnel4_out_src_port=0 tunnel4_out_dst_port=46354"
+ifindex="in_ifindex=$br0_ifindex in_format=0 out_ifindex=$vxlan_sys_ifindex"
+out_count=`grep "$out_tunnel_hdr" sflow.log | grep "$ifindex" | wc -l`
+AT_CHECK([[[[ $out_count -ge 999 ]]]])
+
+in_tunnel_hdr="tunnel4_in_protocol=17 tunnel4_in_src=172.31.1.1 tunnel4_in_dst=172.31.1.100"
+ifindex="in_ifindex=$vxlan_sys_ifindex in_format=0 out_ifindex=$br0_ifindex"
+in_count=`grep "$in_tunnel_hdr" sflow.log | grep "$ifindex" | wc -l`
+AT_CHECK([[[[ $in_count -ge 999 ]]]])
+
+OVS_TRAFFIC_VSWITCHD_STOP
+OVS_APP_EXIT_AND_WAIT([test-sflow])
+AT_CLEANUP
+
+
 AT_SETUP([offloads - set ingress_policing_rate and ingress_policing_burst - offloads disabled])
 AT_KEYWORDS([ingress_policing])
 AT_SKIP_IF([test $HAVE_TC = "no"])