mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 01:51:26 +00:00
netdev-native-tnl: Do not validate already checked checksum.
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. Acked-by: Mike Pattrick <mkp@redhat.com> Signed-off-by: David Marchand <david.marchand@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
parent
71f3dd3e9c
commit
c852a8c767
@ -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(native_tnl_l3csum_checked);
|
||||
COVERAGE_DEFINE(native_tnl_l3csum_err);
|
||||
COVERAGE_DEFINE(native_tnl_l4csum_checked);
|
||||
COVERAGE_DEFINE(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(native_tnl_l3csum_checked);
|
||||
bad_csum = csum(ip, IP_IHL(ip->ip_ihl_ver) * 4);
|
||||
}
|
||||
if (OVS_UNLIKELY(bad_csum)) {
|
||||
COVERAGE_INC(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,18 @@ 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_LIKELY(!bad_csum && !dp_packet_ol_l4_csum_partial(packet))
|
||||
&& OVS_UNLIKELY(!dp_packet_l4_checksum_good(packet))) {
|
||||
uint32_t csum;
|
||||
COVERAGE_INC(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 +259,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(native_tnl_l4csum_err);
|
||||
return NULL;
|
||||
}
|
||||
tnl->flags |= FLOW_TNL_F_CSUM;
|
||||
}
|
||||
@ -449,7 +464,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 +662,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 +1098,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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 native_tnl_l3csum_err], [0], [0
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter 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 native_tnl_l3csum_checked], [0], [0
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter 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 native_tnl_l3csum_err], [0], [0
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter native_tnl_l4csum_err], [0], [1
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter native_tnl_l3csum_checked], [0], [0
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter 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
|
||||
|
@ -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 native_tnl_l3csum_err], [0], [0
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter native_tnl_l4csum_err], [0], [0
|
||||
])
|
||||
dnl Yet csum validation happened on all previous packets.
|
||||
AT_CHECK([ovs-appctl coverage/read-counter native_tnl_l3csum_checked], [0], [12
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter 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 native_tnl_l3csum_err], [0], [5
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter native_tnl_l4csum_err], [0], [3
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter native_tnl_l3csum_checked], [0], [18
|
||||
])
|
||||
AT_CHECK([ovs-appctl coverage/read-counter native_tnl_l4csum_checked], [0], [5
|
||||
])
|
||||
|
||||
AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6408004503007079464000402fba600101025c0101025820000800000001c845000054ba200000400184861e0000011e00000200004227e75400030af3195500000000f265010000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user