Add comprehensive tests for DNS query statistics tracking using coverage counters in ovn-controller.
The test suite includes: - Basic counter functionality (total queries, query types, cache hits, responses sent) - Query type classification (A, AAAA, ANY records) - Cache hit and miss tracking - Error counter verification Tests verify coverage counters using: ovn-appctl -t ovn-controller coverage/read-counter <counter_name> The tests use OVS_WAIT_UNTIL to reliably wait for coverage counters to update before verification, following the pattern used in other OVN controller tests. Signed-off-by: Ketan Supanekar <[email protected]> --- tests/automake.mk | 3 +- tests/ovn-dns-stats.at | 497 +++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + 3 files changed, 500 insertions(+), 1 deletion(-) create mode 100644 tests/ovn-dns-stats.at diff --git a/tests/automake.mk b/tests/automake.mk index c8047371b..db9cea6ee 100644 --- a/tests/automake.mk +++ b/tests/automake.mk @@ -48,7 +48,8 @@ TESTSUITE_AT = \ tests/ovn-vif-plug.at \ tests/ovn-util.at \ tests/ovn-br-controller.at \ - tests/ovn-inc-proc-graph-dump.at + tests/ovn-inc-proc-graph-dump.at \ + tests/ovn-dns-stats.at SYSTEM_DPDK_TESTSUITE_AT = \ tests/system-dpdk-testsuite.at \ diff --git a/tests/ovn-dns-stats.at b/tests/ovn-dns-stats.at new file mode 100644 index 000000000..28cf1877b --- /dev/null +++ b/tests/ovn-dns-stats.at @@ -0,0 +1,497 @@ +AT_BANNER([OVN DNS Statistics]) + +# DNS Statistics - Basic functionality +OVN_FOR_EACH_NORTHD([ +AT_SETUP([dns statistics - basic counters]) +ovn_start + +# Define helper functions +set_dns_params() { + local hname=$1 + local ttl=00000e10 + an_count=0001 + type=0001 + case $hname in + vm1) + query_name=03766d31036f766e036f726700 + expected_dns_answer=${query_name}00010001${ttl}00040a000004 + ;; + vm2) + query_name=03766d32036f766e036f726700 + expected_dns_answer=${query_name}00010001${ttl}00040a000006 + expected_dns_answer=${expected_dns_answer}${query_name}00010001${ttl}000414000004 + an_count=0002 + ;; + vm3) + query_name=03766d33036f766e036f726700 + expected_dns_answer=${query_name}00010001${ttl}000428000004 + ;; + vm1_ipv6_only) + query_name=03766d31036f766e036f726700 + type=001c + expected_dns_answer=${query_name}${type}0001${ttl}0010aef00000000000000000000000000004 + ;; + vm1_ipv4_v6) + query_name=03766d31036f766e036f726700 + type=00ff + an_count=0002 + expected_dns_answer=${query_name}00010001${ttl}00040a000004 + expected_dns_answer=${expected_dns_answer}${query_name}001c0001${ttl}0010 + expected_dns_answer=${expected_dns_answer}aef00000000000000000000000000004 + ;; + vm1_invalid_type) + query_name=03766d31036f766e036f726700 + type=0002 + ;; + esac + local dns_req_header=010201200001000000000000 + local dns_resp_header=010281200001${an_count}00000000 + dns_req_data=${dns_req_header}${query_name}${type}0001 + dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer} +} + +test_dns() { + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6 + local dns_query_data=$7 + shift; shift; shift; shift; shift; shift; shift; + ip_len=`expr 28 + ${#dns_query_data} / 2` + udp_len=`expr $ip_len - 20` + ip_len=$(printf "%x" $ip_len) + udp_len=$(printf "%x" $udp_len) + local request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000 + request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000 + request=${request}${dns_query_data} + + if test $dns_reply != 0; then + local dns_reply=$1 + ip_len=`expr 28 + ${#dns_reply} / 2` + udp_len=`expr $ip_len - 20` + ip_len=$(printf "%x" $ip_len) + udp_len=$(printf "%x" $udp_len) + local reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000 + reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply} + echo $reply >> $inport.expected + else + for outport; do + echo $request >> $outport.expected + done + fi + as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request +} + +check ovn-nbctl ls-add ls1 + +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4" + +check ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4" + +DNS1=`ovn-nbctl create DNS records={}` + +check ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4" +check ovn-nbctl set DNS $DNS1 records:vm2.ovn.org="10.0.0.6" + +check ovn-nbctl set Logical_switch ls1 dns_records="$DNS1" + +net_add n1 +sim_add hv1 + +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +OVN_POPULATE_ARP +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +# Start monitoring OpenFlow +AT_CAPTURE_FILE([ofctl_monitor0.log]) +as hv1 ovs-ofctl -t 300 monitor br-int resume --detach --no-chdir \ +--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log + +# Send DNS query using existing test helper +set_dns_params vm1 +src_ip=`ip_to_hex 10 0 0 4` +dst_ip=`ip_to_hex 10 0 0 1` +dns_reply=1 +test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data + +# Wait for NXT_RESUME +OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +# Verify coverage counters +OVS_WAIT_UNTIL([test 1 = $(as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_total)]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_type_a], [0], [1 +]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_cache_hit], [0], [1 +]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_response_sent], [0], [1 +]) + +# Send another query +set_dns_params vm2 +test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data + +OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +# Verify coverage counters after second query +OVS_WAIT_UNTIL([test 2 = $(as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_total)]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_type_a], [0], [2 +]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_cache_hit], [0], [2 +]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_response_sent], [0], [2 +]) + +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) + +# DNS Statistics - Query types +OVN_FOR_EACH_NORTHD([ +AT_SETUP([dns statistics - query type classification]) +ovn_start + +# Define helper functions +set_dns_params() { + local hname=$1 + local ttl=00000e10 + an_count=0001 + type=0001 + case $hname in + vm1) + query_name=03766d31036f766e036f726700 + expected_dns_answer=${query_name}00010001${ttl}00040a000004 + ;; + vm1_ipv6_only) + query_name=03766d31036f766e036f726700 + type=001c + expected_dns_answer=${query_name}${type}0001${ttl}0010aef00000000000000000000000000004 + ;; + vm1_ipv4_v6) + query_name=03766d31036f766e036f726700 + type=00ff + an_count=0002 + expected_dns_answer=${query_name}00010001${ttl}00040a000004 + expected_dns_answer=${expected_dns_answer}${query_name}001c0001${ttl}0010 + expected_dns_answer=${expected_dns_answer}aef00000000000000000000000000004 + ;; + esac + local dns_req_header=010201200001000000000000 + local dns_resp_header=010281200001${an_count}00000000 + dns_req_data=${dns_req_header}${query_name}${type}0001 + dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer} +} + +test_dns() { + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6 + local dns_query_data=$7 + shift; shift; shift; shift; shift; shift; shift; + ip_len=`expr 28 + ${#dns_query_data} / 2` + udp_len=`expr $ip_len - 20` + ip_len=$(printf "%x" $ip_len) + udp_len=$(printf "%x" $udp_len) + local request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000 + request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000 + request=${request}${dns_query_data} + + if test $dns_reply != 0; then + local dns_reply=$1 + ip_len=`expr 28 + ${#dns_reply} / 2` + udp_len=`expr $ip_len - 20` + ip_len=$(printf "%x" $ip_len) + udp_len=$(printf "%x" $udp_len) + local reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000 + reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply} + echo $reply >> $inport.expected + else + for outport; do + echo $request >> $outport.expected + done + fi + as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request +} + +check ovn-nbctl ls-add ls1 + +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4" + +check ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4 aef0::4" + +DNS1=`ovn-nbctl create DNS records={}` +check ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4 aef0::4" + +check ovn-nbctl set Logical_switch ls1 dns_records="$DNS1" + +net_add n1 +sim_add hv1 + +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +OVN_POPULATE_ARP +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +AT_CAPTURE_FILE([ofctl_monitor0.log]) +as hv1 ovs-ofctl -t 300 monitor br-int resume --detach --no-chdir \ +--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log + +src_ip=`ip_to_hex 10 0 0 4` +dst_ip=`ip_to_hex 10 0 0 1` +dns_reply=1 + +# Send A record query +set_dns_params vm1 +test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data +OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +# Send AAAA record query +set_dns_params vm1_ipv6_only +test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data +OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +# Send ANY record query +set_dns_params vm1_ipv4_v6 +test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data +OVS_WAIT_UNTIL([test 3 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +# Verify coverage counters +OVS_WAIT_UNTIL([test 3 = $(as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_total)]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_type_a], [0], [1 +]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_type_aaaa], [0], [1 +]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_type_any], [0], [1 +]) + +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) + +# DNS Statistics - Cache misses +OVN_FOR_EACH_NORTHD([ +AT_SETUP([dns statistics - cache hits and misses]) +ovn_start + +# Define helper functions +set_dns_params() { + local hname=$1 + local ttl=00000e10 + an_count=0001 + type=0001 + case $hname in + vm1) + query_name=03766d31036f766e036f726700 + expected_dns_answer=${query_name}00010001${ttl}00040a000004 + ;; + vm3) + query_name=03766d33036f766e036f726700 + expected_dns_answer=${query_name}00010001${ttl}000428000004 + ;; + esac + local dns_req_header=010201200001000000000000 + local dns_resp_header=010281200001${an_count}00000000 + dns_req_data=${dns_req_header}${query_name}${type}0001 + dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer} +} + +test_dns() { + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6 + local dns_query_data=$7 + shift; shift; shift; shift; shift; shift; shift; + ip_len=`expr 28 + ${#dns_query_data} / 2` + udp_len=`expr $ip_len - 20` + ip_len=$(printf "%x" $ip_len) + udp_len=$(printf "%x" $udp_len) + local request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000 + request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000 + request=${request}${dns_query_data} + + if test $dns_reply != 0; then + local dns_reply=$1 + ip_len=`expr 28 + ${#dns_reply} / 2` + udp_len=`expr $ip_len - 20` + ip_len=$(printf "%x" $ip_len) + udp_len=$(printf "%x" $udp_len) + local reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000 + reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply} + echo $reply >> $inport.expected + else + for outport; do + echo $request >> $outport.expected + done + fi + as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request +} + +check ovn-nbctl ls-add ls1 + +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4" + +check ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4" + +DNS1=`ovn-nbctl create DNS records={}` +check ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4" + +check ovn-nbctl set Logical_switch ls1 dns_records="$DNS1" + +net_add n1 +sim_add hv1 + +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +OVN_POPULATE_ARP +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +AT_CAPTURE_FILE([ofctl_monitor0.log]) +as hv1 ovs-ofctl -t 300 monitor br-int resume --detach --no-chdir \ +--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log + +src_ip=`ip_to_hex 10 0 0 4` +dst_ip=`ip_to_hex 10 0 0 1` +dns_reply=1 + +# Query for existing record (cache hit) +set_dns_params vm1 +test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data $dns_resp_data +OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +# Query for non-existing record (cache miss) +set_dns_params vm3 +dns_reply=0 +test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip $dns_reply $dns_req_data +OVS_WAIT_UNTIL([test 2 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +# Verify coverage counters +OVS_WAIT_UNTIL([test 2 = $(as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_total)]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_cache_hit], [0], [1 +]) +AT_CHECK([as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_cache_miss], [0], [1 +]) + +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) + +# DNS Statistics - Error counters +OVN_FOR_EACH_NORTHD([ +AT_SETUP([dns statistics - error counters]) +ovn_start + +# Define helper functions +set_dns_params() { + local hname=$1 + local ttl=00000e10 + an_count=0001 + type=0001 + case $hname in + vm1_invalid_type) + query_name=03766d31036f766e036f726700 + type=0002 + ;; + esac + local dns_req_header=010201200001000000000000 + local dns_resp_header=010281200001${an_count}00000000 + dns_req_data=${dns_req_header}${query_name}${type}0001 + dns_resp_data=${dns_resp_header}${query_name}${type}0001${expected_dns_answer} +} + +test_dns() { + local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 dns_reply=$6 + local dns_query_data=$7 + shift; shift; shift; shift; shift; shift; shift; + ip_len=`expr 28 + ${#dns_query_data} / 2` + udp_len=`expr $ip_len - 20` + ip_len=$(printf "%x" $ip_len) + udp_len=$(printf "%x" $udp_len) + local request=${dst_mac}${src_mac}0800450000${ip_len}0000000080110000 + request=${request}${src_ip}${dst_ip}9234003500${udp_len}0000 + request=${request}${dns_query_data} + + if test $dns_reply != 0; then + local dns_reply=$1 + ip_len=`expr 28 + ${#dns_reply} / 2` + udp_len=`expr $ip_len - 20` + ip_len=$(printf "%x" $ip_len) + udp_len=$(printf "%x" $udp_len) + local reply=${src_mac}${dst_mac}0800450000${ip_len}0000000080110000 + reply=${reply}${dst_ip}${src_ip}0035923400${udp_len}0000${dns_reply} + echo $reply >> $inport.expected + else + for outport; do + echo $request >> $outport.expected + done + fi + as hv1 ovs-appctl netdev-dummy/receive hv1-vif$inport $request +} + +check ovn-nbctl ls-add ls1 + +check ovn-nbctl lsp-add ls1 ls1-lp1 \ +-- lsp-set-addresses ls1-lp1 "f0:00:00:00:00:01 10.0.0.4" + +check ovn-nbctl lsp-set-port-security ls1-lp1 "f0:00:00:00:00:01 10.0.0.4" + +DNS1=`ovn-nbctl create DNS records={}` +check ovn-nbctl set DNS $DNS1 records:vm1.ovn.org="10.0.0.4" + +check ovn-nbctl set Logical_switch ls1 dns_records="$DNS1" + +net_add n1 +sim_add hv1 + +as hv1 +ovs-vsctl add-br br-phys +ovn_attach n1 br-phys 192.168.0.1 +ovs-vsctl -- add-port br-int hv1-vif1 -- \ + set interface hv1-vif1 external-ids:iface-id=ls1-lp1 \ + options:tx_pcap=hv1/vif1-tx.pcap \ + options:rxq_pcap=hv1/vif1-rx.pcap \ + ofport-request=1 + +OVN_POPULATE_ARP +wait_for_ports_up +check ovn-nbctl --wait=hv sync + +AT_CAPTURE_FILE([ofctl_monitor0.log]) +as hv1 ovs-ofctl -t 300 monitor br-int resume --detach --no-chdir \ +--pidfile=ovs-ofctl0.pid 2> ofctl_monitor0.log + +src_ip=`ip_to_hex 10 0 0 4` +dst_ip=`ip_to_hex 10 0 0 1` +dns_reply=1 + +# Test with invalid query type (should increment unsupported counter) +set_dns_params vm1_invalid_type +test_dns 1 f00000000001 f000000000f0 $src_ip $dst_ip 0 $dns_req_data +OVS_WAIT_UNTIL([test 1 = `cat ofctl_monitor*.log | grep -c NXT_RESUME`]) + +# Verify coverage counter +OVS_WAIT_UNTIL([test 1 = $(as hv1 ovs-appctl -t ovn-controller coverage/read-counter dns_query_total)]) + +OVN_CLEANUP([hv1]) +AT_CLEANUP +]) + diff --git a/tests/testsuite.at b/tests/testsuite.at index 6216ac761..4fa203187 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -43,3 +43,4 @@ m4_include([tests/ovn-vif-plug.at]) m4_include([tests/ovn-util.at]) m4_include([tests/ovn-br-controller.at]) m4_include([tests/ovn-inc-proc-graph-dump.at]) +m4_include([tests/ovn-dns-stats.at]) -- 2.52.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
