summaryrefslogtreecommitdiffstats
path: root/xdp-dump/tests/test-xdpdump.sh
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xdp-dump/tests/test-xdpdump.sh731
1 files changed, 731 insertions, 0 deletions
diff --git a/xdp-dump/tests/test-xdpdump.sh b/xdp-dump/tests/test-xdpdump.sh
new file mode 100644
index 0000000..dc5da13
--- /dev/null
+++ b/xdp-dump/tests/test-xdpdump.sh
@@ -0,0 +1,731 @@
+#
+# Test scrip to do basic xdpdump checks
+#
+# shellcheck disable=2039
+#
+ALL_TESTS="test_help test_interfaces test_capt_pcap test_capt_pcapng test_capt_term test_exitentry test_snap test_multi_pkt test_perf_wakeup test_promiscuous_selfload test_promiscuous_preload test_none_xdp test_pname_parse test_multi_prog test_xdp_load"
+
+XDPDUMP=${XDPDUMP:-./xdpdump}
+XDP_LOADER=${XDP_LOADER:-../xdp-loader/xdp-loader}
+
+RESULT=""
+
+print_result()
+{
+ if [ -n "$1" ]; then
+ echo "ERROR: $1"
+ echo "==== RESULT: ===="
+ echo "$RESULT"
+ echo "==== END ===="
+ else
+ echo "$RESULT"
+ fi
+}
+
+test_help()
+{
+ local XDPDUMP_HELP_TEXT
+ XDPDUMP_HELP_TEXT=$(cat <<-END
+
+Usage: xdpdump [options]
+
+ XDPDump tool to dump network traffic
+
+Options:
+ --rx-capture <mode> Capture point for the rx direction (valid values: entry,exit)
+ -D, --list-interfaces Print the list of available interfaces
+ --load-xdp-mode <mode> Mode used for --load-xdp-mode, default native (valid values: native,skb,hw,unspecified)
+ --load-xdp-program Load XDP trace program if no XDP program is loaded
+ -i, --interface <ifname> Name of interface to capture on
+ --perf-wakeup <events> Wake up xdpdump every <events> packets
+ -p, --program-names <prog> Specific program to attach to
+ -P, --promiscuous-mode Open interface in promiscuous mode
+ -s, --snapshot-length <snaplen> Minimum bytes of packet to capture
+ --use-pcap Use legacy pcap format for XDP traces
+ -w, --write <file> Write raw packets to pcap file
+ -x, --hex Print the full packet in hex
+ -v, --verbose Enable verbose logging (-vv: more verbose)
+ --version Display version information
+ -h, --help Show this help
+
+END
+ )
+
+ $XDPDUMP --help | grep -q "\-\-perf-wakeup"
+ if [ $? -eq 1 ]; then
+ XDPDUMP_HELP_TEXT=$(echo "$XDPDUMP_HELP_TEXT" | sed '/--perf-wakeup <events>/d')
+ fi
+
+ RESULT=$($XDPDUMP --help)
+ if [ "$RESULT" != "$XDPDUMP_HELP_TEXT" ]; then
+ print_result "The --help output failed"
+ return 1
+ fi
+ RESULT=$($XDPDUMP -h)
+ if [ "$RESULT" != "$XDPDUMP_HELP_TEXT" ]; then
+ print_result "The -h output failed"
+ return 1
+ fi
+}
+
+test_interfaces()
+{
+ local NO_PROG_REGEX="($NS +<No XDP program loaded!>)"
+ if is_multiprog_supported; then
+ local PROG_REGEX="($NS[[:space:]]+xdp_dispatcher.+xdp_drop)"
+ else
+ local PROG_REGEX="($NS[[:space:]]+xdp_drop)"
+ fi
+
+ RESULT=$($XDPDUMP -D)
+ if ! [[ $RESULT =~ $NO_PROG_REGEX ]]; then
+ print_result "Failed showing test interface with no XPD program loaded"
+ return 1
+ fi
+
+ RESULT=$($XDPDUMP --list-interfaces)
+ if ! [[ $RESULT =~ $NO_PROG_REGEX ]]; then
+ print_result "Failed showing test interface with no XPD program loaded"
+ return 1
+ fi
+
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/xdp_drop.o"
+
+ RESULT=$($XDPDUMP -D)
+ if ! [[ $RESULT =~ $PROG_REGEX ]]; then
+ print_result "Failed showing test interface with XPD program loaded"
+ return 1
+ fi
+
+ $XDP_LOADER unload "$NS" --all
+}
+
+test_capt_pcap()
+{
+ skip_if_missing_kernel_symbol bpf_xdp_output_proto
+ skip_if_missing_trace_attach
+
+ local PASS_PKT="IP6 $INSIDE_IP6 > $OUTSIDE_IP6: ICMP6, echo reply(, id [0-9]+)?, seq 1, length 64"
+
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" || return 1
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name --use-pcap -w - 2> /dev/null | tcpdump -r - -n")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ sleep 1
+ RESULT=$(stop_background "$PID")
+
+ $XDP_LOADER unload "$NS" --all || return 1
+
+ if ! [[ $RESULT =~ $PASS_PKT ]]; then
+ print_result "IPv6 packet not received"
+ return 1
+ fi
+}
+
+version_greater_or_equal()
+{
+ printf '%s\n%s\n' "$2" "$1" | sort -V -C
+}
+
+test_capt_pcapng()
+{
+ skip_if_missing_kernel_symbol bpf_xdp_output_proto
+ skip_if_missing_trace_attach
+
+ local PCAP_FILE="/tmp/${NS}_PID_$$_$RANDOM.pcap"
+ local PASS_PKT="IP6 $INSIDE_IP6 > $OUTSIDE_IP6: ICMP6, echo reply(, id [0-9]+)?, seq 1, length 64"
+ local HW=$(uname -m | sed -e 's/[]\/$*+.^|[]/\\&/g')
+ local OS=$(uname -snrv | sed -e 's/[]\/$+*.^()|[]/\\&/g')
+ local INFOS_REGEX=""
+ local OLD_CAPINFOS=0
+ local TSHARK_VERSION=$(tshark --version 2> /dev/null | sed -ne 's/^TShark (Wireshark) \([0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p')
+
+ if [[ "$(capinfos --help)" == *"Capinfos (Wireshark) 2."* ]]; then
+ OLD_CAPINFOS=1
+ fi
+
+ INFOS_REGEX+="(File type: Wireshark\/\.\.\. - pcapng.*"
+ INFOS_REGEX+="Capture hardware: $HW.*"
+ INFOS_REGEX+="Capture oper-sys: $OS.*"
+ INFOS_REGEX+="Capture application: xdpdump v[0-9]+\.[0-9]+\.[0-9]+.*"
+ INFOS_REGEX+="Capture comment: Capture was taken on interface xdptest, with the following XDP programs loaded: xdp_dispatcher\(\) xdp_test_prog_w.*"
+ INFOS_REGEX+="Interface #0 info:.*"
+ INFOS_REGEX+="Name = ${NS}:xdp_test_prog_with_a_long_name\(\)@fentry.*"
+ if [ $OLD_CAPINFOS -eq 0 ]; then
+ INFOS_REGEX+="Hardware = driver: \"veth\", version: \"1\.0\", fw-version: \"\", rom-version: \"\", bus-info: \"\".*"
+ fi
+ INFOS_REGEX+="Time precision = nanoseconds \(9\).*"
+ INFOS_REGEX+="Interface #1 info:.*"
+ INFOS_REGEX+="Name = ${NS}:xdp_test_prog_with_a_long_name\(\)@fexit.*"
+ if [ $OLD_CAPINFOS -eq 0 ]; then
+ INFOS_REGEX+="Hardware = driver: \"veth\", version: \"1\.0\", fw-version: \"\", rom-version: \"\", bus-info: \"\".*"
+ fi
+ INFOS_REGEX+="Time precision = nanoseconds \(9\))"
+
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" || return 1
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name -w - 2> /dev/null | tcpdump -r - -n")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+
+ if ! [[ $RESULT =~ $PASS_PKT ]]; then
+ print_result "IPv6 packet not received"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name -w $PCAP_FILE --rx-capture=entry,exit")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || (rm "$PCAP_FILE" >& /dev/null; return 1)
+ RESULT=$(stop_background "$PID") || (print_result "xdpdump failed"; rm "$PCAP_FILE" >& /dev/null; return 1)
+
+ RESULT=$(capinfos "$PCAP_FILE") || (print_result "capinfos failed"; rm "$PCAP_FILE" >& /dev/null; return 1)
+ if ! [[ $RESULT =~ $INFOS_REGEX ]]; then
+ echo "REGEX: $INFOS_REGEX"
+ print_result "Failed capinfos content"
+ rm "$PCAP_FILE" >& /dev/null
+ return 1
+ fi
+
+ if version_greater_or_equal "$TSHARK_VERSION" 3.6.7; then
+ local ATTRIB_REGEX="^xdptest:xdp_test_prog_with_a_long_name\(\)@fentry 0 1 $.*^xdptest:xdp_test_prog_with_a_long_name\(\)@fexit 0 1 2$.*"
+ RESULT=$(tshark -r "$PCAP_FILE" -T fields \
+ -e frame.interface_name \
+ -e frame.interface_queue \
+ -e frame.packet_id \
+ -e frame.verdict.ebpf_xdp)
+ if ! [[ $RESULT =~ $ATTRIB_REGEX ]]; then
+ print_result "Failed attributes content with Tshark $TSHARK_VERSION"
+ rm "$PCAP_FILE" >& /dev/null
+ return 1
+ fi
+ fi
+
+ rm "$PCAP_FILE" >& /dev/null
+
+ $XDP_LOADER unload "$NS" --all || return 1
+}
+
+test_capt_term()
+{
+ skip_if_missing_kernel_symbol bpf_xdp_output_proto
+ skip_if_missing_trace_attach
+
+ local PASS_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local PASS_X_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes, captured 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local PASS_X_OPT="0x0020: 00 00 00 00 00 02 fc 42 de ad ca fe 00 01 00 00"
+
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" || return 1
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+
+ if ! [[ $RESULT =~ $PASS_REGEX ]]; then
+ print_result "IPv6 packet not received"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name -x")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+
+ if ! [[ $RESULT =~ $PASS_X_REGEX ]]; then
+ print_result "IPv6 packet not received[2]"
+ return 1
+ fi
+
+ # If the IP6 addresses remain the same this simple string compare can be
+ # used to verify the -x output is present.
+ if [[ "$RESULT" != *"$PASS_X_OPT"* ]]; then
+ print_result "IPv6 HEX packet not received"
+ return 1
+ fi
+
+ $XDP_LOADER unload "$NS" --all || return 1
+}
+
+test_exitentry()
+{
+ skip_if_missing_kernel_symbol bpf_xdp_output_proto
+ skip_if_missing_trace_attach
+
+ local PASS_ENTRY_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local PASS_EXIT_REGEX="(xdp_test_prog_with_a_long_name\(\)@exit\[PASS\]: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local PASS_ENTRY_D_REGEX="(xdp_drop\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local PASS_EXIT_D_REGEX="(xdp_drop\(\)@exit\[DROP\]: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local ID_ENTRY_REGEX="xdp_drop\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id ([0-9]+)"
+ local ID_EXIT_REGEX="xdp_drop\(\)@exit\[DROP\]: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id ([0-9]+)"
+
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" || return 1
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name --rx-capture=entry")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $PASS_ENTRY_REGEX ]]; then
+ print_result "IPv6 entry packet not received"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name --rx-capture=exit")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $PASS_EXIT_REGEX ]]; then
+ print_result "IPv6 exit packet not received"
+ return 1
+ fi
+
+ $XDP_LOADER unload "$NS" --all || return 1
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/xdp_drop.o" || return 1
+
+ PID=$(start_background "$XDPDUMP -i $NS --rx-capture=exit")
+ $PING6 -W 1 -c 1 "$INSIDE_IP6" # Note that this ping will fail!!
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $PASS_EXIT_D_REGEX ]]; then
+ print_result "IPv6 drop exit packet not received"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS --rx-capture=exit,entry")
+ $PING6 -W 1 -c 1 "$INSIDE_IP6" # Note that this ping will fail!!
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $PASS_EXIT_D_REGEX && $RESULT =~ $PASS_ENTRY_D_REGEX ]]; then
+ print_result "IPv6 drop entry/exit packet not received"
+ return 1
+ fi
+
+ [[ $RESULT =~ $ID_ENTRY_REGEX ]]
+ ENTRY_ID=${BASH_REMATCH[1]}
+ [[ $RESULT =~ $ID_EXIT_REGEX ]]
+ EXIT_ID=${BASH_REMATCH[1]}
+ if [[ "$EXIT_ID" != "$ENTRY_ID" ]]; then
+ print_result "Failed matching IDs"
+ return 1
+ fi
+
+ $XDP_LOADER unload "$NS" --all || return 1
+}
+
+test_snap()
+{
+ skip_if_missing_kernel_symbol bpf_xdp_output_proto
+ skip_if_missing_trace_attach
+
+ local PASS_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes, captured 16 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local PASS_II_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes, captured 21 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" || return 1
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name -x --snapshot-length=16")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+
+ if ! [[ $RESULT =~ $PASS_REGEX ]]; then
+ print_result "IPv6 packet fragment not received"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name -x -s 21")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+
+ if ! [[ $RESULT =~ $PASS_II_REGEX ]]; then
+ print_result "IPv6 packet fragment not received[2]"
+ return 1
+ fi
+
+ $XDP_LOADER unload "$NS" --all || return 1
+}
+
+test_multi_pkt()
+{
+ skip_if_missing_kernel_symbol bpf_xdp_output_proto
+ skip_if_missing_trace_attach
+
+ local PASS_ENTRY_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size [0-9]+ bytes on if_index [0-9]+, rx queue [0-9]+, id 20000)"
+ local PASS_EXIT_REGEX="(xdp_test_prog_with_a_long_name\(\)@exit\[PASS\]: packet size [0-9]+ bytes on if_index [0-9]+, rx queue [0-9]+, id 20000)"
+ local PKT_SIZES=(56 512 1500)
+
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" || return 1
+
+ for PKT_SIZE in "${PKT_SIZES[@]}" ; do
+
+ PID=$(start_background_no_stderr "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name --rx-capture=entry,exit")
+ timeout 40 $PING6 -q -W 2 -s "$PKT_SIZE" -c 20000 -f "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $PASS_ENTRY_REGEX ]]; then
+ print_result "IPv6 entry packet not received, $PKT_SIZE"
+ return 1
+ fi
+
+ if ! [[ $RESULT =~ $PASS_EXIT_REGEX ]]; then
+ print_result "IPv6 exit packet not received, $PKT_SIZE"
+ return 1
+ fi
+ done
+
+ $XDP_LOADER unload "$NS" --all || return 1
+}
+
+test_perf_wakeup()
+{
+ skip_if_missing_kernel_symbol bpf_xdp_output_proto
+ skip_if_missing_trace_attach
+
+ $XDPDUMP --help | grep -q "\-\-perf-wakeup"
+ if [ $? -eq 1 ]; then
+ # No support for perf_wakeup, so return SKIP
+ return "$SKIPPED_TEST"
+ fi
+
+ local PASS_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+)"
+ local PASS_10K_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id 10000)"
+ local WAKEUPS=(0 1 32 128)
+
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" || return 1
+
+ for WAKEUP in "${WAKEUPS[@]}" ; do
+
+ # We send a single packet to make sure flushing of the buffer works!
+ PID=$(start_background_no_stderr "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name --perf-wakeup=$WAKEUP")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+
+ if ! [[ $RESULT =~ $PASS_REGEX ]]; then
+ print_result "IPv6 packet not received for wakeup $WAKEUP"
+ return 1
+ fi
+
+ # We sent 10k packets and see if the all arrive
+ PID=$(start_background_no_stderr "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name --perf-wakeup=$WAKEUP")
+ timeout 20 "$PING6" -q -W 2 -c 10000 -f "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $PASS_10K_REGEX ]]; then
+ print_result "IPv6 10k packet not received for wakeup $WAKEUP"
+ return 1
+ fi
+ done
+
+ $XDP_LOADER unload "$NS" --all || return 1
+}
+
+test_none_xdp()
+{
+ local PASS_PKT="packet size 118 bytes on if_name \"$NS\""
+ local WARN_MSG="WARNING: Specified interface does not have an XDP program loaded,"
+
+ $XDP_LOADER unload "$NS" --all
+
+ PID=$(start_background "$XDPDUMP -i $NS")
+ $PING6 -W 2 -c 4 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if [[ "$RESULT" != *"$PASS_PKT"* ]]; then
+ print_result "IPv6 packet not received"
+ return 1
+ fi
+ if [[ "$RESULT" != *"$WARN_MSG"* ]]; then
+ print_result "Missing warning message"
+ return 1
+ fi
+}
+
+test_promiscuous_selfload()
+{
+ local PASS_PKT="packet size 118 bytes on if_name \"$NS\""
+ local PASS_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes, captured 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+
+ $XDP_LOADER unload "$NS" --all
+ dmesg -C
+
+ PID=$(start_background "$XDPDUMP -i $NS -P")
+ $PING6 -W 2 -c 4 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if [[ "$RESULT" != *"$PASS_PKT"* ]]; then
+ print_result "IPv6 packet not received [legacy mode]"
+ return 1
+ fi
+
+ RESULT=$(dmesg)
+ if [[ "$RESULT" != *"device $NS entered promiscuous mode"* ]]; then
+ print_result "Failed enabling promiscuous mode on legacy interface"
+ return 1
+ fi
+ if [[ "$RESULT" != *"device $NS left promiscuous mode"* ]]; then
+ print_result "Failed disabling promiscuous mode on legacy interface"
+ return 1
+ fi
+}
+
+test_promiscuous_preload()
+{
+ skip_if_missing_kernel_symbol bpf_xdp_output
+ skip_if_missing_trace_attach
+
+ local PASS_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes, captured 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" || return 1
+ dmesg -C
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name -x --promiscuous-mode")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $PASS_REGEX ]]; then
+ print_result "IPv6 packet not received"
+ return 1
+ fi
+
+ RESULT=$(dmesg)
+ if [[ "$RESULT" != *"device $NS entered promiscuous mode"* ]]; then
+ print_result "Failed enabling promiscuous mode on interface"
+ return 1
+ fi
+ if [[ "$RESULT" != *"device $NS left promiscuous mode"* ]]; then
+ print_result "Failed disabling promiscuous mode on interface"
+ return 1
+ fi
+}
+
+test_pname_parse()
+{
+ skip_if_legacy_fallback
+
+ local PASS_REGEX="(xdp_test_prog_with_a_long_name\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local PROG_ID_1=0
+ local PROG_ID_2=0
+ local PROG_ID_3=0
+ local PROG_ID_4=0
+
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+
+ # Here we load the programs without the xdp-tools loader to make sure
+ # they are not loaded as a multi-program.
+ $TEST_PROG_DIR/test-tool load -m skb "$NS" "$TEST_PROG_DIR/test_long_func_name.o"
+
+ # We need to specify the function name or else it should fail
+ PID=$(start_background "$XDPDUMP -i $NS")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Can't identify the full XDP main function!"* ]]; then
+ print_result "xdpdump should fail with duplicate function!"
+ return 1
+ fi
+
+ # Here we specify the correct function name so we should get the packet
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $PASS_REGEX ]]; then
+ print_result "IPv6 packet not received"
+ return 1
+ fi
+
+ # Here we specify the wrong correct function name so we should not get the packet
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name_too")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Can't load eBPF object:"* ]]; then
+ print_result "xdpdump should fail being unable to attach!"
+ return 1
+ fi
+
+ # Here we specify an non-existing function
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_non_existing_name")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Can't find function 'xdp_test_prog_with_a_long_non_existing_name' on interface!"* ]]; then
+ print_result "xdpdump should fail with unknown function!"
+ return 1
+ fi
+
+ # Verify invalid program indexes
+ PID=$(start_background "$XDPDUMP -i $NS -p hallo@3e")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Can't extract valid program id from \"hallo@3e\"!"* ]]; then
+ print_result "xdpdump should fail with id value error!"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p hallo@128")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Invalid program id supplied, \"hallo@128\"!"* ]]; then
+ print_result "xdpdump should fail with invalid id!"
+ return 1
+ fi
+
+ # Remove loaded program
+ ip link set dev "$NS" xdpgeneric off
+
+ # Now test actual multi-program parsing (negative test cases)
+ $XDP_LOADER unload "$NS" --all
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" "$TEST_PROG_DIR/xdp_pass.o" "$TEST_PROG_DIR/xdp_drop.o"
+
+ PID=$(start_background "$XDPDUMP -D")
+ RESULT=$(stop_background "$PID")
+ PROG_ID_1=$(echo "$RESULT" | grep "$NS" -A4 | cut -c51-55 | sed -n 1p | tr -d ' ')
+ PROG_ID_2=$(echo "$RESULT" | grep "$NS" -A4 | cut -c51-55 | sed -n 2p | tr -d ' ')
+ PROG_ID_3=$(echo "$RESULT" | grep "$NS" -A4 | cut -c51-55 | sed -n 3p | tr -d ' ')
+ PROG_ID_4=$(echo "$RESULT" | grep "$NS" -A4 | cut -c51-55 | sed -n 4p | tr -d ' ')
+
+ PID=$(start_background "$XDPDUMP -i $NS -p all")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Can't identify the full XDP 'xdp_test_prog_w' function in program $PROG_ID_2!"* ||
+ $RESULT != *"xdp_test_prog_with_a_long_name@$PROG_ID_2"* ||
+ $RESULT != *"xdp_test_prog_with_a_long_name_too@$PROG_ID_2"* ||
+ $RESULT != *"Command line to replace 'all':"* ||
+ $RESULT != *"xdp_dispatcher@$PROG_ID_1,<function_name>@$PROG_ID_2,xdp_pass@$PROG_ID_3,xdp_drop@$PROG_ID_4"* ]]; then
+ print_result "xdpdump should fail with all list!"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p hallo@$PROG_ID_1")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Can't find function 'hallo' in interface program $PROG_ID_1!"* ]]; then
+ print_result "xdpdump should fail with hallo not found on program $PROG_ID_1!"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p hallo")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Can't find function 'hallo' on interface"* ]]; then
+ print_result "xdpdump should fail hallo not found!"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_w")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Can't identify the full XDP 'xdp_test_prog_w' function!"* ||
+ $RESULT != *"xdp_test_prog_with_a_long_name_too"* ]]; then
+ print_result "xdpdump should fail can't id xdp_test_prog_w!"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_w@$PROG_ID_2")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: Can't identify the full XDP 'xdp_test_prog_w' function in program $PROG_ID_2!"* ||
+ $RESULT != *"xdp_test_prog_with_a_long_name_too@$PROG_ID_2"* ]]; then
+ print_result "xdpdump should fail can't id xdp_test_prog_w@$PROG_ID_2!"
+ return 1
+ fi
+
+ # Now load XDP programs with duplicate functions
+ $XDP_LOADER unload "$NS" --all
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/test_long_func_name.o" "$TEST_PROG_DIR/test_long_func_name.o" "$TEST_PROG_DIR/xdp_pass.o" "$TEST_PROG_DIR/xdp_drop.o"
+
+ PID=$(start_background "$XDPDUMP -D")
+ RESULT=$(stop_background "$PID")
+ PROG_ID_1=$(echo "$RESULT" | grep "$NS" -A2 | cut -c51-55 | sed -n 1p | tr -d ' ')
+ PROG_ID_2=$(echo "$RESULT" | grep "$NS" -A2 | cut -c51-55 | sed -n 2p | tr -d ' ')
+ PROG_ID_3=$(echo "$RESULT" | grep "$NS" -A2 | cut -c51-55 | sed -n 2p | tr -d ' ')
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_test_prog_with_a_long_name")
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT != *"ERROR: The function 'xdp_test_prog_with_a_long_name' exists in multiple programs!"* ||
+ $RESULT != *"xdp_test_prog_with_a_long_name@$PROG_ID_2"* ||
+ $RESULT != *"xdp_test_prog_with_a_long_name@$PROG_ID_3"* ]]; then
+ print_result "xdpdump should fail with duplicate function!"
+ return 1
+ fi
+
+ $XDP_LOADER unload "$NS" --all
+ return 0
+}
+
+test_multi_prog()
+{
+ skip_if_legacy_fallback
+ skip_if_missing_trace_attach
+
+ local ENTRY_REGEX="(xdp_dispatcher\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+).*(xdp_pass\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local EXIT_REGEX="(xdp_pass\(\)@exit\[PASS\]: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+).*(xdp_dispatcher\(\)@exit\[PASS\]: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local PROG_ID_1=0
+ local PROG_ID_4=0
+
+ $XDP_LOADER load "$NS" "$TEST_PROG_DIR/xdp_pass.o" "$TEST_PROG_DIR/test_long_func_name.o" "$TEST_PROG_DIR/xdp_pass.o"
+
+ PID=$(start_background "$XDPDUMP -D")
+ RESULT=$(stop_background "$PID")
+ PROG_ID_1=$(echo "$RESULT" | grep "$NS" -A4 | cut -c51-55 | sed -n 1p | tr -d ' ')
+ PROG_ID_4=$(echo "$RESULT" | grep "$NS" -A4 | cut -c51-55 | sed -n 4p | tr -d ' ')
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_dispatcher,xdp_pass@$PROG_ID_4 -vv")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if [[ $RESULT == *"Unrecognized arg#0 type PTR"* ]]; then
+ $XDP_LOADER unload "$NS" --all
+ return $SKIPPED_TEST
+ fi
+ if ! [[ $RESULT =~ $ENTRY_REGEX ]]; then
+ print_result "Not received all fentry packets"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_dispatcher,xdp_pass@$PROG_ID_4 --rx-capture=exit")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $EXIT_REGEX ]]; then
+ print_result "Not received all fexit packets"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_dispatcher,xdp_pass@$PROG_ID_4 --rx-capture=exit,entry")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $ENTRY_REGEX ]]; then
+ print_result "Not received all fentry packets on entry/exit test"
+ return 1
+ fi
+ if ! [[ $RESULT =~ $EXIT_REGEX ]]; then
+ print_result "Not received all fexit packets on entry/exit test"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p $PROG_ID_1,$PROG_ID_4 --rx-capture=exit,entry")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $ENTRY_REGEX ]]; then
+ print_result "[IDs]Not received all fentry packets on entry/exit test"
+ return 1
+ fi
+ if ! [[ $RESULT =~ $EXIT_REGEX ]]; then
+ print_result "[IDs]Not received all fexit packets on entry/exit test"
+ return 1
+ fi
+
+ PID=$(start_background "$XDPDUMP -i $NS -p xdp_dispatcher,$PROG_ID_4 --rx-capture=exit,entry")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if ! [[ $RESULT =~ $ENTRY_REGEX ]]; then
+ print_result "[Mix]Not received all fentry packets on entry/exit test"
+ return 1
+ fi
+ if ! [[ $RESULT =~ $EXIT_REGEX ]]; then
+ print_result "[Mix]Not received all fexit packets on entry/exit test"
+ return 1
+ fi
+
+ $XDP_LOADER unload "$NS" --all
+ return 0
+}
+
+test_xdp_load()
+{
+ local PASS_REGEX="(xdpdump\(\)@entry: packet size 118 bytes on if_index [0-9]+, rx queue [0-9]+, id [0-9]+)"
+ local WARN_MSG="Will load a capture only XDP program!"
+
+ PID=$(start_background "$XDPDUMP -i $NS --load-xdp-program")
+ $PING6 -W 2 -c 1 "$INSIDE_IP6" || return 1
+ RESULT=$(stop_background "$PID")
+ if [[ "$RESULT" != *"$WARN_MSG"* ]]; then
+ print_result "Missing warning message"
+ return 1
+ fi
+ if ! [[ $RESULT =~ $PASS_REGEX ]]; then
+ print_result "IPv6 packet not received"
+ return 1
+ fi
+}
+
+cleanup_tests()
+{
+ $XDP_LOADER unload "$NS" --all >/dev/null 2>&1
+}