Commit 952e0ee3 authored by Petr Machata's avatar Petr Machata Committed by David S. Miller

selftests: forwarding: lib: Add helpers for checksum handling

In order to generate IGMPv3 and MLDv2 packets on the fly, we will need
helpers to calculate the packet checksum.

The approach presented in this patch revolves around payload templates
for mausezahn. These are mausezahn-like payload strings (01:23:45:...)
with possibly one 2-byte sequence replaced with the word PAYLOAD. The
main function is payload_template_calc_checksum(), which calculates
RFC 1071 checksum of the message. There are further helpers to then
convert the checksum to the payload format, and to expand it.

For IPv6, MLDv2 message checksum is computed using a pseudoheader that
differs from the header used in the payload itself. The fact that the
two messages are different means that the checksum needs to be
returned as a separate quantity, instead of being expanded in-place in
the payload itself. Furthermore, the pseudoheader includes a length of
the message. Much like the checksum, this needs to be expanded in
mausezahn format. And likewise for number of addresses for (S,G)
entries. Thus we have several places where a computed quantity needs
to be presented in the payload format. Add a helper u16_to_bytes(),
which will be used in all these cases.
Signed-off-by: default avatarPetr Machata <petrm@nvidia.com>
Acked-by: default avatarNikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fcf49276
...@@ -1709,6 +1709,62 @@ ipv6_to_bytes() ...@@ -1709,6 +1709,62 @@ ipv6_to_bytes()
expand_ipv6 "$IP" : expand_ipv6 "$IP" :
} }
u16_to_bytes()
{
local u16=$1; shift
printf "%04x" $u16 | sed 's/^/000/;s/^.*\(..\)\(..\)$/\1:\2/'
}
# Given a mausezahn-formatted payload (colon-separated bytes given as %02x),
# possibly with a keyword CHECKSUM stashed where a 16-bit checksum should be,
# calculate checksum as per RFC 1071, assuming the CHECKSUM field (if any)
# stands for 00:00.
payload_template_calc_checksum()
{
local payload=$1; shift
(
# Set input radix.
echo "16i"
# Push zero for the initial checksum.
echo 0
# Pad the payload with a terminating 00: in case we get an odd
# number of bytes.
echo "${payload%:}:00:" |
sed 's/CHECKSUM/00:00/g' |
tr '[:lower:]' '[:upper:]' |
# Add the word to the checksum.
sed 's/\(..\):\(..\):/\1\2+\n/g' |
# Strip the extra odd byte we pushed if left unconverted.
sed 's/\(..\):$//'
echo "10000 ~ +" # Calculate and add carry.
echo "FFFF r - p" # Bit-flip and print.
) |
dc |
tr '[:upper:]' '[:lower:]'
}
payload_template_expand_checksum()
{
local payload=$1; shift
local checksum=$1; shift
local ckbytes=$(u16_to_bytes $checksum)
echo "$payload" | sed "s/CHECKSUM/$ckbytes/g"
}
payload_template_nbytes()
{
local payload=$1; shift
payload_template_expand_checksum "${payload%:}" 0 |
sed 's/:/\n/g' | wc -l
}
igmpv3_is_in_get() igmpv3_is_in_get()
{ {
local igmpv3 local igmpv3
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment