Skip to content

Commit

Permalink
dp-packet: Correct IPv4 checksum calculation.
Browse files Browse the repository at this point in the history
During the transition towards checksum offloading, the function to
handle software fallback of IPv4 checksums didn't account for the
options field.

Fixes: 5d11c47 ("userspace: Enable IP checksum offloading by default.")
Reported-by: Jun Wang <[email protected]>
Reported-at: https://mail.openvswitch.org/pipermail/ovs-discuss/2024-July/053236.html
Signed-off-by: Mike Pattrick <[email protected]>
Signed-off-by: Ilya Maximets <[email protected]>
  • Loading branch information
mkp-rh authored and igsilya committed Aug 15, 2024
1 parent 6b6823a commit b0e749b
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
31 changes: 28 additions & 3 deletions lib/dp-packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,16 @@ dp_packet_inner_l3(const struct dp_packet *b)
: NULL;
}

static inline size_t
dp_packet_inner_l3_size(const struct dp_packet *b)
{
return OVS_LIKELY(b->inner_l3_ofs != UINT16_MAX)
? (const char *) dp_packet_tail(b)
- (const char *) dp_packet_inner_l3(b)
- dp_packet_l2_pad_size(b)
: 0;
}

static inline void *
dp_packet_inner_l4(const struct dp_packet *b)
{
Expand Down Expand Up @@ -1390,11 +1400,26 @@ dp_packet_hwol_l3_ipv4(const struct dp_packet *b)
static inline void
dp_packet_ip_set_header_csum(struct dp_packet *p, bool inner)
{
struct ip_header *ip = (inner) ? dp_packet_inner_l3(p) : dp_packet_l3(p);
struct ip_header *ip;
size_t l3_size;
size_t ip_len;

if (inner) {
ip = dp_packet_inner_l3(p);
l3_size = dp_packet_inner_l3_size(p);
} else {
ip = dp_packet_l3(p);
l3_size = dp_packet_l3_size(p);
}

ovs_assert(ip);
ip->ip_csum = 0;
ip->ip_csum = csum(ip, sizeof *ip);

ip_len = IP_IHL(ip->ip_ihl_ver) * 4;

if (OVS_LIKELY(ip_len >= IP_HEADER_LEN && ip_len < l3_size)) {
ip->ip_csum = 0;
ip->ip_csum = csum(ip, ip_len);
}
}

/* Returns 'true' if the packet 'p' has good integrity and the
Expand Down
35 changes: 35 additions & 0 deletions tests/dpif-netdev.at
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,41 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p1 ${bad_frame}])
AT_CHECK([ovs-pcap p2.pcap > p2.pcap.txt 2>&1])
AT_CHECK_UNQUOTED([tail -n 1 p2.pcap.txt], [0], [${good_expected}
])

dnl Test with IP optional fields in a valid packet. Note that neither this
dnl packet nor the following one contain a correct checksum. OVS is
dnl expected to replace this dummy checksum with a valid one if possible.
m4_define([OPT_PKT], m4_join([],
dnl eth(dst=aa:aa:aa:aa:aa:aa,src=bb:bb:bb:bb:bb:bb,type=0x0800)
[aaaaaaaaaaaabbbbbbbbbbbb0800],
dnl ipv4(dst=10.0.0.2,src=10.0.0.1,proto=1,len=60,tot_len=68,csum=0xeeee)
[4f000044abab00004001eeee0a0000010a000002],
dnl IPv4 Opt: type 7 (Record Route) len 39 + type 0 (EOL).
[07270c010203040a000003000000000000000000],
[0000000000000000000000000000000000000000],
dnl icmp(type=8,code=0), csum 0x3e2f incorrect, should be 0x412f.
[08003e2fb6d00000]))

dnl IP header indicates optional fields but doesn't contain any.
m4_define([MICROGRAM], m4_join([],
dnl eth(dst=aa:aa:aa:aa:aa:aa,src=bb:bb:bb:bb:bb:bb,type=0x0800)
[aaaaaaaaaaaabbbbbbbbbbbb0800],
dnl ipv4(dst=10.0.0.2,src=10.0.0.1,proto=1,len=60,tot_len=68,csum=0xeeee)
[4f000044abab00004001eeee0a0000010a000002]))

AT_CHECK([ovs-vsctl set Interface p1 options:ol_ip_csum=true])
AT_CHECK([ovs-vsctl set Interface p1 options:ol_ip_csum_set_good=true])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 OPT_PKT])
AT_CHECK([ovs-appctl netdev-dummy/receive p1 MICROGRAM])
AT_CHECK([ovs-pcap p2.pcap > p2.pcap.txt 2>&1])

dnl Build the expected modified packets. The first packet has a valid IPv4
dnl checksum and modified destination IP address. The second packet isn't
dnl expected to change.
AT_CHECK([echo "OPT_PKT" | sed -e "s/0a000002/c0a80101/" -e "s/eeee/dd2e/" > expout])
AT_CHECK([echo "MICROGRAM" >> expout])
AT_CHECK([tail -n 2 p2.pcap.txt], [0], [expout])

OVS_VSWITCHD_STOP
AT_CLEANUP

Expand Down

0 comments on commit b0e749b

Please sign in to comment.