Skip to content

Commit

Permalink
odp-execute: Fix AVX checksum calculation.
Browse files Browse the repository at this point in the history
The AVX implementation for calculating checksums was not
handling carry-over addition correctly in some cases.
This patch adds an additional shuffle to add 16-bit padding to
the final part of the calculation to handle such cases. This
commit also adds a unit test to check the checksum carry-bits
issue with actions autovalidator enabled.

Reported-by: Eelco Chaudron <[email protected]>
Signed-off-by: Emma Finn <[email protected]>
Signed-off-by: Eelco Chaudron <[email protected]>
  • Loading branch information
emmaLfinn00 authored and chaudron committed May 30, 2024
1 parent 4d25656 commit 7af0716
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
5 changes: 5 additions & 0 deletions lib/odp-execute-avx512.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ avx512_get_delta(__m256i old_header, __m256i new_header)
0xF, 0xF, 0xF, 0xF);
v_delta = _mm256_permutexvar_epi32(v_swap32a, v_delta);

v_delta = _mm256_hadd_epi32(v_delta, v_zeros);
v_delta = _mm256_shuffle_epi8(v_delta, v_swap16a);
v_delta = _mm256_hadd_epi32(v_delta, v_zeros);
v_delta = _mm256_hadd_epi16(v_delta, v_zeros);

Expand Down Expand Up @@ -575,6 +577,9 @@ avx512_ipv6_sum_header(__m512i ip6_header)
0xF, 0xF, 0xF, 0xF);

v_delta = _mm256_permutexvar_epi32(v_swap32a, v_delta);

v_delta = _mm256_hadd_epi32(v_delta, v_zeros);
v_delta = _mm256_shuffle_epi8(v_delta, v_swap16a);
v_delta = _mm256_hadd_epi32(v_delta, v_zeros);
v_delta = _mm256_hadd_epi16(v_delta, v_zeros);

Expand Down
63 changes: 63 additions & 0 deletions tests/dpif-netdev.at
Original file line number Diff line number Diff line change
Expand Up @@ -1091,3 +1091,66 @@ OVS_VSWITCHD_STOP(["dnl
/Error: unknown miniflow extract implementation superstudy./d
/Error: invalid study_pkt_cnt value: -pmd./d"])
AT_CLEANUP

AT_SETUP([datapath - Actions Autovalidator Checksum])

OVS_VSWITCHD_START(add-port br0 p0 -- set Interface p0 type=dummy \
-- add-port br0 p1 -- set Interface p1 type=dummy)

AT_CHECK([ovs-appctl odp-execute/action-impl-set autovalidator], [0], [dnl
Action implementation set to autovalidator.
])

dnl Add flows to trigger checksum calculation.
AT_DATA([flows.txt], [dnl
in_port=p0,ip,actions=mod_nw_src=10.1.1.1,p1
in_port=p0,ipv6,actions=set_field:fc00::100->ipv6_src,p1
])
AT_CHECK([ovs-ofctl del-flows br0])
AT_CHECK([ovs-ofctl -Oopenflow13 add-flows br0 flows.txt])

dnl Make sure checksum won't be offloaded.
AT_CHECK([ovs-vsctl set Interface p0 options:ol_ip_csum=false])
AT_CHECK([ovs-vsctl set Interface p0 options:ol_ip_csum_set_good=false])

AT_CHECK([ovs-vsctl set Interface p1 options:pcap=p1.pcap])

dnl IPv4 packet with values that will trigger carry-over addition for checksum.
flow_s_v4="
eth_src=47:42:86:08:17:50,eth_dst=3e:55:b5:9e:3a:fb,dl_type=0x0800,
nw_src=229.167.36.90,nw_dst=130.161.64.186,nw_proto=6,nw_ttl=64,nw_frag=no,
tp_src=54392,tp_dst=5201,tcp_flags=ack"

good_frame=$(ovs-ofctl compose-packet --bare "${flow_s_v4}")
AT_CHECK([ovs-appctl netdev-dummy/receive p0 ${good_frame}])

dnl Checksum should change to 0xAC33 with ip_src changed to 10.1.1.1
dnl by the datapath while processing the packet.
flow_expected=$(echo "${flow_s_v4}" | sed 's/229.167.36.90/10.1.1.1/g')
good_expected=$(ovs-ofctl compose-packet --bare "${flow_expected}")
AT_CHECK([ovs-pcap p1.pcap > p1.pcap.txt 2>&1])
AT_CHECK_UNQUOTED([tail -n 1 p1.pcap.txt], [0], [${good_expected}
])

dnl Repeat similar test for IPv6.
flow_s_v6="
eth_src=8a:bf:7e:2f:05:84,eth_dst=0a:8f:39:4f:e0:73,dl_type=0x86dd,
ipv6_src=2f8a:2076:3926:9e7:2d47:4bc9:9c7:17f3,
ipv6_dst=7287:10dd:2fb9:41d5:3eb2:2c7a:11b0:6258,
ipv6_label=0x51ac,nw_proto=6,nw_ttl=142,nw_frag=no,
tp_src=20405,tp_dst=20662,tcp_flags=ack"

good_frame_v6=$(ovs-ofctl compose-packet --bare "${flow_s_v6}")
AT_CHECK([ovs-appctl netdev-dummy/receive p0 ${good_frame_v6}])

dnl Checksum should change to 0x59FD with ipv6_src changed to fc00::100
dnl by the datapath while processing the packet.
flow_expected_v6=$(echo "${flow_s_v6}" | \
sed 's/2f8a:2076:3926:9e7:2d47:4bc9:9c7:17f3/fc00::100/g')
good_expected_v6=$(ovs-ofctl compose-packet --bare "${flow_expected_v6}")
AT_CHECK([ovs-pcap p1.pcap > p1.pcap.txt 2>&1])
AT_CHECK_UNQUOTED([tail -n 1 p1.pcap.txt], [0], [${good_expected_v6}
])

OVS_VSWITCHD_STOP
AT_CLEANUP

0 comments on commit 7af0716

Please sign in to comment.