selftests: ovpn: add notification parsing and matching

To verify that netlink notifications are correctly emitted and contain
the expected fields, this commit uses the tools/net/ynl/pyynl/cli.py
script to create multicast listeners. These listeners record the
captured notifications to a JSON file, which is later compared to the
expected output.

Cc: linux-kselftest@vger.kernel.org
Cc: shuah@kernel.org
Cc: horms@kernel.org
Signed-off-by: Ralf Lici <ralf@mandelbit.com>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
This commit is contained in:
Ralf Lici 2025-06-13 17:55:39 +02:00 committed by Antonio Quartulli
parent c841b676da
commit 77de28cd7c
18 changed files with 76 additions and 3 deletions

View File

@ -23,7 +23,14 @@ endif
LDLIBS += $(NL_LDLIBS)
TEST_FILES = common.sh
TEST_FILES = \
common.sh \
data64.key \
json \
tcp_peers.txt \
udp_peers.txt \
../../../../net/ynl/pyynl/cli.py \
# end of TEST_FILES
TEST_PROGS := \
test-chachapoly.sh \

View File

@ -7,12 +7,18 @@
UDP_PEERS_FILE=${UDP_PEERS_FILE:-udp_peers.txt}
TCP_PEERS_FILE=${TCP_PEERS_FILE:-tcp_peers.txt}
OVPN_CLI=${OVPN_CLI:-./ovpn-cli}
YNL_CLI=${YNL_CLI:-../../../../net/ynl/pyynl/cli.py}
ALG=${ALG:-aes}
PROTO=${PROTO:-UDP}
FLOAT=${FLOAT:-0}
JQ_FILTER='map(select(.msg.peer | has("remote-ipv6") | not)) |
map(del(.msg.ifindex)) | sort_by(.msg.peer.id)[]'
LAN_IP="11.11.11.11"
declare -A tmp_jsons=()
declare -A listener_pids=()
create_ns() {
ip netns add peer${1}
}
@ -48,6 +54,14 @@ setup_ns() {
ip -n peer${1} link set tun${1} up
}
setup_listener() {
file=$(mktemp)
PYTHONUNBUFFERED=1 ip netns exec peer${p} ${YNL_CLI} --family ovpn \
--subscribe peers --output-json --duration 40 > ${file} &
listener_pids[$1]=$!
tmp_jsons[$1]="${file}"
}
add_peer() {
if [ "${PROTO}" == "UDP" ]; then
if [ ${1} -eq 0 ]; then
@ -82,6 +96,24 @@ add_peer() {
fi
}
compare_ntfs() {
if [ ${#tmp_jsons[@]} -gt 0 ]; then
[ "$FLOAT" == 1 ] && suffix="-float"
expected="json/peer${1}${suffix}.json"
received="${tmp_jsons[$1]}"
kill -TERM ${listener_pids[$1]} || true
wait ${listener_pids[$1]} || true
printf "Checking notifications for peer ${1}... "
if diff <(jq -s "${JQ_FILTER}" ${expected}) \
<(jq -s "${JQ_FILTER}" ${received}); then
echo "OK"
fi
rm -f ${received} || true
fi
}
cleanup() {
# some ovpn-cli processes sleep in background so they need manual poking
killall $(basename ${OVPN_CLI}) 2>/dev/null || true
@ -104,5 +136,3 @@ if [ "${PROTO}" == "UDP" ]; then
else
NUM_PEERS=${NUM_PEERS:-$(wc -l ${TCP_PEERS_FILE} | awk '{print $1}')}
fi

View File

@ -0,0 +1,9 @@
{"name": "peer-float-ntf", "msg": {"ifindex": 0, "peer": {"id": 1, "remote-ipv4": "10.10.1.3", "remote-port": 1}}}
{"name": "peer-float-ntf", "msg": {"ifindex": 0, "peer": {"id": 2, "remote-ipv4": "10.10.2.3", "remote-port": 1}}}
{"name": "peer-float-ntf", "msg": {"ifindex": 0, "peer": {"id": 3, "remote-ipv4": "10.10.3.3", "remote-port": 1}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 1}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 2}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 3}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 4}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 5}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 6}}}

View File

@ -0,0 +1,6 @@
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 1}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 2}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 3}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 4}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 5}}}
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 6}}}

View File

@ -0,0 +1 @@
peer1.json

View File

@ -0,0 +1 @@
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 1}}}

View File

@ -0,0 +1 @@
peer2.json

View File

@ -0,0 +1 @@
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 2}}}

View File

@ -0,0 +1 @@
peer3.json

View File

@ -0,0 +1 @@
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 3}}}

View File

@ -0,0 +1 @@
peer4.json

View File

@ -0,0 +1 @@
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 4}}}

View File

@ -0,0 +1 @@
peer5.json

View File

@ -0,0 +1 @@
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 5}}}

View File

@ -0,0 +1 @@
peer6.json

View File

@ -0,0 +1 @@
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 6}}}

View File

@ -3,3 +3,4 @@
3 5.5.5.4
4 5.5.5.5
5 5.5.5.6
6 5.5.5.7

View File

@ -17,6 +17,10 @@ for p in $(seq 0 ${NUM_PEERS}); do
create_ns ${p}
done
for p in $(seq 0 ${NUM_PEERS}); do
setup_listener ${p}
done
for p in $(seq 0 ${NUM_PEERS}); do
setup_ns ${p} 5.5.5.$((${p} + 1))/24 ${MTU}
done
@ -112,6 +116,10 @@ for p in $(seq 3 ${NUM_PEERS}); do
done
sleep 5
for p in $(seq 0 ${NUM_PEERS}); do
compare_ntfs ${p}
done
cleanup
modprobe -r ovpn || true