Bad packets were still being validated in software when decapsulating
a IP header. Trust decision taken wrt IP checksum offloading (checking
dp_packet_hwol_l3_csum_ipv4_ol()) and avoid revalidating a known
bad checksum.

While at it, add coverage counters so that checksum validation impact
can be monitored, and unit tests.

Signed-off-by: David Marchand <david.march...@redhat.com>
---
 lib/netdev-native-tnl.c       | 50 ++++++++++++++++--------
 lib/netdev-native-tnl.h       |  3 --
 tests/tunnel-push-pop-ipv6.at | 30 +++++++++++++-
 tests/tunnel-push-pop.at      | 73 ++++++++++++++++++++++++++++++++---
 4 files changed, 130 insertions(+), 26 deletions(-)

diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index 62e1a0c870..cbb875bd26 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -33,6 +33,7 @@
 #include <sys/time.h>
 
 #include "byte-order.h"
+#include "coverage.h"
 #include "csum.h"
 #include "dp-packet.h"
 #include "netdev.h"
@@ -49,6 +50,11 @@
 VLOG_DEFINE_THIS_MODULE(native_tnl);
 static struct vlog_rate_limit err_rl = VLOG_RATE_LIMIT_INIT(60, 5);
 
+COVERAGE_DEFINE(netdev_native_tnl_l3csum_checked);
+COVERAGE_DEFINE(netdev_native_tnl_l3csum_err);
+COVERAGE_DEFINE(netdev_native_tnl_l4csum_checked);
+COVERAGE_DEFINE(netdev_native_tnl_l4csum_err);
+
 #define VXLAN_HLEN   (sizeof(struct udp_header) +         \
                       sizeof(struct vxlanhdr))
 
@@ -82,8 +88,8 @@ netdev_tnl_get_src_port(struct dp_packet *packet)
     return htons(hash + tnl_udp_port_min);
 }
 
-void *
-netdev_tnl_ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl,
+static void *
+ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl,
                   unsigned int *hlen)
 {
     void *nh;
@@ -107,16 +113,20 @@ netdev_tnl_ip_extract_tnl_md(struct dp_packet *packet, 
struct flow_tnl *tnl,
               ((char *)nh - (char *)dp_packet_data(packet));
 
     if (IP_VER(ip->ip_ihl_ver) == 4) {
-
+        bool bad_csum = dp_packet_ip_checksum_bad(packet);
         ovs_be32 ip_src, ip_dst;
 
         /* A packet coming from a network device might have the
          * csum already checked. In this case, skip the check. */
-        if (OVS_UNLIKELY(!dp_packet_hwol_l3_csum_ipv4_ol(packet))) {
-            if (csum(ip, IP_IHL(ip->ip_ihl_ver) * 4)) {
-                VLOG_WARN_RL(&err_rl, "ip packet has invalid checksum");
-                return NULL;
-            }
+        if (OVS_UNLIKELY(!bad_csum
+                         && !dp_packet_hwol_l3_csum_ipv4_ol(packet))) {
+            COVERAGE_INC(netdev_native_tnl_l3csum_checked);
+            bad_csum = csum(ip, IP_IHL(ip->ip_ihl_ver) * 4);
+        }
+        if (OVS_UNLIKELY(bad_csum)) {
+            COVERAGE_INC(netdev_native_tnl_l3csum_err);
+            VLOG_WARN_RL(&err_rl, "ip packet has invalid checksum");
+            return NULL;
         }
 
         if (ntohs(ip->ip_tot_len) > l3_size) {
@@ -227,15 +237,19 @@ udp_extract_tnl_md(struct dp_packet *packet, struct 
flow_tnl *tnl,
 {
     struct udp_header *udp;
 
-    udp = netdev_tnl_ip_extract_tnl_md(packet, tnl, hlen);
+    udp = ip_extract_tnl_md(packet, tnl, hlen);
     if (!udp) {
         return NULL;
     }
 
     if (udp->udp_csum) {
-        if (OVS_LIKELY(!dp_packet_ol_l4_csum_partial(packet)) &&
-            OVS_UNLIKELY(!dp_packet_l4_checksum_good(packet))) {
+        bool bad_csum = dp_packet_l4_checksum_bad(packet);
+
+        if (OVS_UNLIKELY(!bad_csum)
+            && OVS_LIKELY(!dp_packet_ol_l4_csum_partial(packet))
+            && OVS_UNLIKELY(!dp_packet_l4_checksum_good(packet))) {
             uint32_t csum;
+            COVERAGE_INC(netdev_native_tnl_l4csum_checked);
             if (netdev_tnl_is_header_ipv6(dp_packet_data(packet))) {
                 csum = packet_csum_pseudoheader6(dp_packet_l3(packet));
             } else {
@@ -246,9 +260,11 @@ udp_extract_tnl_md(struct dp_packet *packet, struct 
flow_tnl *tnl,
                                  ((const unsigned char *)udp -
                                   (const unsigned char *)dp_packet_eth(packet)
                                  ));
-            if (csum_finish(csum)) {
-                return NULL;
-            }
+            bad_csum = csum_finish(csum);
+        }
+        if (OVS_UNLIKELY(bad_csum)) {
+            COVERAGE_INC(netdev_native_tnl_l4csum_err);
+            return NULL;
         }
         tnl->flags |= FLOW_TNL_F_CSUM;
     }
@@ -449,7 +465,7 @@ parse_gre_header(struct dp_packet *packet,
     unsigned int ulen;
     uint16_t greh_protocol;
 
-    greh = netdev_tnl_ip_extract_tnl_md(packet, tnl, &ulen);
+    greh = ip_extract_tnl_md(packet, tnl, &ulen);
     if (!greh) {
         return -EINVAL;
     }
@@ -647,7 +663,7 @@ netdev_erspan_pop_header(struct dp_packet *packet)
         goto err;
     }
 
-    greh = netdev_tnl_ip_extract_tnl_md(packet, tnl, &ulen);
+    greh = ip_extract_tnl_md(packet, tnl, &ulen);
     if (!greh) {
         goto err;
     }
@@ -1083,7 +1099,7 @@ netdev_srv6_pop_header(struct dp_packet *packet)
     }
 
     pkt_metadata_init_tnl(md);
-    if (!netdev_tnl_ip_extract_tnl_md(packet, tnl, &hlen)) {
+    if (!ip_extract_tnl_md(packet, tnl, &hlen)) {
         goto err;
     }
 
diff --git a/lib/netdev-native-tnl.h b/lib/netdev-native-tnl.h
index 5d8f1672a8..47d6b6bbcf 100644
--- a/lib/netdev-native-tnl.h
+++ b/lib/netdev-native-tnl.h
@@ -125,9 +125,6 @@ extern uint16_t tnl_udp_port_max;
 
 ovs_be16 netdev_tnl_get_src_port(struct dp_packet *);
 
-void *
-netdev_tnl_ip_extract_tnl_md(struct dp_packet *packet, struct flow_tnl *tnl,
-                             unsigned int *hlen);
 void *
 netdev_tnl_push_ip_header(struct dp_packet *packet, const void *header,
                           int size, int *ip_tot_size, ovs_be32 ipv6_label);
diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
index 824a226b21..4934b97259 100644
--- a/tests/tunnel-push-pop-ipv6.at
+++ b/tests/tunnel-push-pop-ipv6.at
@@ -402,7 +402,7 @@ AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], 
[dnl
 2001:cafe::92                                 f8:bc:12:44:34:c8   br0
 ])
 
-dnl Receiving Neighbot Advertisement with incorrect VLAN id should not alter 
tunnel neighbor cache
+dnl Receiving Neighbor Advertisement with incorrect VLAN id should not alter 
tunnel neighbor cache
 AT_CHECK([ovs-vsctl set port br0 tag=10])
 AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x8100),vlan(vid=99,pcp=7),encap(eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6))'])
 
@@ -587,6 +587,34 @@ AT_CHECK([tail -1 stdout], [0],
   [Datapath actions: 
tnl_push(tnl_port(4789),header(size=70,type=4,eth(dst=f8:bc:12:44:ca:fe,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=17,tclass=0x0,hlimit=64),udp(src=0,dst=4789,csum=0xffff),vxlan(flags=0x8000000,vni=0x7b)),out_port(100)),1
 ])
 
+dnl No drop so far.
+AT_CHECK([ovs-appctl coverage/read-counter datapath_drop_tunnel_pop_error], 
[0], [0
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l3csum_err], [0], 
[0
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l4csum_err], [0], 
[0
+])
+dnl Yet csum validation happened on all previous packets (with non null 
checksums).
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l3csum_checked], 
[0], [0
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l4csum_checked], 
[0], [1
+])
+
+
+dnl Send a VXLAN packet with bad UDP checksum.
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000f8bc1244cafe86dd60000000003a11402001cafe0000000000000000000000922001cafe000000000000000000000088c85312b5003aDEAD0c00000300007b00ffffffffffff00000000000008004500001c0001000040117cce7f0000017f0000010035003500080172'])
+
+AT_CHECK([ovs-appctl coverage/read-counter datapath_drop_tunnel_pop_error], 
[0], [1
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l3csum_err], [0], 
[0
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l4csum_err], [0], 
[1
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l3csum_checked], 
[0], [0
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l4csum_checked], 
[0], [2
+])
+
 AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl
 2001:cafe::92                                 f8:bc:12:44:ca:fe   br0
 2001:cafe::93                                 f8:bc:12:44:34:b7   br0
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index cf4e622014..35a9dc4944 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -514,6 +514,30 @@ AT_CHECK([tail -1 stdout], [0],
 ])
 AT_CHECK([ovs-ofctl del-flows int-br])
 
+dnl Check decapsulation of VXLAN packet
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003a00000800000000007b00fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003a02320800000000007b00fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003a202e0c00000300015900fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+ovs-appctl time/warp 1000
+AT_CHECK([ovs-ofctl dump-ports int-br | grep -E 'port  [[248]]:' | sort], [0], 
[dnl
+  port  2: rx pkts=2, bytes=84, drop=?, errs=?, frame=?, over=?, crc=?
+  port  4: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+  port  8: rx pkts=1, bytes=42, drop=?, errs=?, frame=?, over=?, crc=?
+])
+
+dnl Idem, with Rx cksum good
+AT_CHECK([ovs-vsctl set interface p0 options:ol_ip_rx_csum_set_good=true])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003a00000800000000007b00fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003a02320800000000007b00fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003a202e0c00000300015900fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+AT_CHECK([ovs-vsctl set interface p0 options:ol_ip_rx_csum_set_good=false])
+ovs-appctl time/warp 1000
+AT_CHECK([ovs-ofctl dump-ports int-br | grep -E 'port  [[248]]:' | sort], [0], 
[dnl
+  port  2: rx pkts=4, bytes=168, drop=?, errs=?, frame=?, over=?, crc=?
+  port  4: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+  port  8: rx pkts=2, bytes=84, drop=?, errs=?, frame=?, over=?, crc=?
+])
+
 dnl Check decapsulation of GRE packet
 AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500007e79464000402fba550101025c0101025820006558000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
 AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500007e79464000402fba550101025c0101025820006558000001c8fe71d883724fbeb6f4e1494a080045000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
@@ -535,14 +559,53 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port  7'], 
[0], [dnl
   port  7: rx pkts=3, bytes=252, drop=?, errs=?, frame=?, over=?, crc=?
 ])
 
-AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500007079464000402fba600101025c0101025820000800000001c845000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
+dnl No drop so far.
+AT_CHECK([ovs-appctl coverage/read-counter datapath_drop_tunnel_pop_error], 
[0], [0
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l3csum_err], [0], 
[0
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l4csum_err], [0], 
[0
+])
+dnl Yet csum validation happened on all previous packets.
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l3csum_checked], 
[0], [12
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l4csum_checked], 
[0], [4
+])
+
+dnl Send various incorrect bad IP checksum packets.
+dnl GRE
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500007079464000402fDEAD0101025c0101025820000800000001c845000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
+dnl VxLAN
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e000100004011DEAD0101025c0101025812b512b5003a00000800000000007b00fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+dnl VxLAN-GPE
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e000100004011DEAD0101025c0101025812b512b5003a202e0c00000300015900fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+
+dnl Idem, with Rx cksum bad but with a valid and an invalid packet.
+AT_CHECK([ovs-vsctl set interface p0 options:ol_ip_rx_csum_set_bad=true])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003a02320800000000007b00fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500007079464000402fDEAD0101025c0101025820000800000001c845000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
+AT_CHECK([ovs-vsctl set interface p0 options:ol_ip_rx_csum_set_bad=false])
+
+dnl Send various incorrect bad UDP checksum packets.
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003aDEAD0800000000007b00fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+
+dnl Idem, with Rx cksum bad but with a valid and an invalid packet.
+AT_CHECK([ovs-vsctl set interface p0 options:ol_l4_rx_csum_set_bad=true])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003a02320800000000007b00fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004500004e00010000401173e90101025c0101025812b512b5003aDEAD0800000000007b00fe71d883724fbeb6f4e1494a08004500001c0001000040013ede1e0000011e0000020000ffff00000000'])
+AT_CHECK([ovs-vsctl set interface p0 options:ol_l4_rx_csum_set_bad=false])
 
 ovs-appctl time/warp 5000
 
-AT_CHECK([
-ovs-appctl coverage/read-counter datapath_drop_tunnel_pop_error
-], [0], [dnl
-1
+AT_CHECK([ovs-appctl coverage/read-counter datapath_drop_tunnel_pop_error], 
[0], [8
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l3csum_err], [0], 
[5
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l4csum_err], [0], 
[3
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l3csum_checked], 
[0], [18
+])
+AT_CHECK([ovs-appctl coverage/read-counter netdev_native_tnl_l4csum_checked], 
[0], [5
 ])
 
 AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'aa55aa550000001b213cab6408004503007079464000402fba600101025c0101025820000800000001c845000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
-- 
2.48.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to