unbound_munin_ revision 356345
1228753Smm#!/bin/sh 2228753Smm# 3228753Smm# plugin for munin to monitor usage of unbound servers. 4228753Smm# To install copy this to /usr/local/share/munin/plugins/unbound_munin_ 5228753Smm# and use munin-node-configure (--suggest, --shell). 6228753Smm# 7228753Smm# (C) 2008 W.C.A. Wijngaards. BSD Licensed. 8228753Smm# 9228753Smm# To install; enable statistics and unbound-control in unbound.conf 10228753Smm# server: extended-statistics: yes 11228753Smm# statistics-cumulative: no 12228753Smm# statistics-interval: 0 13228753Smm# remote-control: control-enable: yes 14228753Smm# Run the command unbound-control-setup to generate the key files. 15228753Smm# 16228753Smm# Environment variables for this script 17228753Smm# statefile - where to put temporary statefile. 18228753Smm# unbound_conf - where the unbound.conf file is located. 19228753Smm# unbound_control - where to find unbound-control executable. 20228753Smm# spoof_warn - what level to warn about spoofing 21228753Smm# spoof_crit - what level to crit about spoofing 22228753Smm# 23228753Smm# You can set them in your munin/plugin-conf.d/plugins.conf file 24228753Smm# with: 25228753Smm# [unbound*] 26228753Smm# user root 27228753Smm# env.statefile /usr/local/var/munin/plugin-state/unbound-state 28228753Smm# env.unbound_conf /usr/local/etc/unbound/unbound.conf 29228753Smm# env.unbound_control /usr/local/sbin/unbound-control 30228753Smm# env.spoof_warn 1000 31228753Smm# env.spoof_crit 100000 32228753Smm# 33228753Smm# This plugin can create different graphs depending on what name 34228753Smm# you link it as (with ln -s) into the plugins directory 35228753Smm# You can link it multiple times. 36228753Smm# If you are only a casual user, the _hits and _by_type are most interesting, 37228753Smm# possibly followed by _by_rcode. 38228753Smm# 39228753Smm# unbound_munin_hits - base volume, cache hits, unwanted traffic 40228753Smm# unbound_munin_queue - to monitor the internal requestlist 41228753Smm# unbound_munin_memory - memory usage 42228753Smm# unbound_munin_by_type - incoming queries by type 43228753Smm# unbound_munin_by_class - incoming queries by class 44228753Smm# unbound_munin_by_opcode - incoming queries by opcode 45228753Smm# unbound_munin_by_rcode - answers by rcode, validation status 46228753Smm# unbound_munin_by_flags - incoming queries by flags 47228753Smm# unbound_munin_histogram - histogram of query resolving times 48228753Smm# 49228753Smm# Magic markers - optional - used by installation scripts and 50228753Smm# munin-config: (originally contrib family but munin-node-configure ignores it) 51228753Smm# 52228753Smm#%# family=auto 53228753Smm#%# capabilities=autoconf suggest 54228753Smm 55228753Smm# POD documentation 56228753Smm: <<=cut 57228753Smm=head1 NAME 58228753Smm 59228753Smmunbound_munin_ - Munin plugin to monitor the Unbound DNS resolver. 60228753Smm 61228753Smm=head1 APPLICABLE SYSTEMS 62228753Smm 63228753SmmSystem with unbound daemon. 64228753Smm 65228753Smm=head1 CONFIGURATION 66228753Smm 67228753Smm [unbound*] 68228753Smm user root 69228753Smm env.statefile /usr/local/var/munin/plugin-state/unbound-state 70228753Smm env.unbound_conf /usr/local/etc/unbound/unbound.conf 71228753Smm env.unbound_control /usr/local/sbin/unbound-control 72228753Smm env.spoof_warn 1000 73228753Smm env.spoof_crit 100000 74228753Smm 75228753SmmUse the .env settings to override the defaults. 76228753Smm 77228753Smm=head1 USAGE 78228753Smm 79228753SmmCan be used to present different graphs. Use ln -s for that name in 80228753Smmthe plugins directory to enable the graph. 81228753Smmunbound_munin_hits - base volume, cache hits, unwanted traffic 82228753Smmunbound_munin_queue - to monitor the internal requestlist 83228753Smmunbound_munin_memory - memory usage 84228753Smmunbound_munin_by_type - incoming queries by type 85228753Smmunbound_munin_by_class - incoming queries by class 86228753Smmunbound_munin_by_opcode - incoming queries by opcode 87228753Smmunbound_munin_by_rcode - answers by rcode, validation status 88228753Smmunbound_munin_by_flags - incoming queries by flags 89228753Smmunbound_munin_histogram - histogram of query resolving times 90228753Smm 91228753Smm=head1 AUTHOR 92228753Smm 93228753SmmCopyright 2008 W.C.A. Wijngaards 94228753Smm 95228753Smm=head1 LICENSE 96228753Smm 97228753SmmBSD 98228753Smm 99228753Smm=cut 100228753Smm 101228753Smmstate=${statefile:-/usr/local/var/munin/plugin-state/unbound-state} 102228753Smmconf=${unbound_conf:-/usr/local/etc/unbound/unbound.conf} 103228753Smmctrl=${unbound_control:-/usr/local/sbin/unbound-control} 104228753Smmwarn=${spoof_warn:-1000} 105228753Smmcrit=${spoof_crit:-100000} 106228753Smmlock=$state.lock 107228753Smm 108228753Smm# number of seconds between polling attempts. 109228753Smm# makes the statefile hang around for at least this many seconds, 110228753Smm# so that multiple links of this script can share the results. 111228753Smmlee=55 112228753Smm 113228753Smm# to keep things within 19 characters 114228753SmmABBREV="-e s/total/t/ -e s/thread/t/ -e s/num/n/ -e s/query/q/ -e s/answer/a/ -e s/unwanted/u/ -e s/requestlist/ql/ -e s/type/t/ -e s/class/c/ -e s/opcode/o/ -e s/rcode/r/ -e s/edns/e/ -e s/mem/m/ -e s/cache/c/ -e s/mod/m/" 115228753Smm 116228753Smm# get value from $1 into return variable $value 117228753Smmget_value ( ) { 118228753Smm value="`grep '^'$1'=' $state | sed -e 's/^.*=//'`" 119228753Smm if test "$value"x = ""x; then 120228753Smm value="0" 121228753Smm fi 122228753Smm} 123228753Smm 124228753Smm# download the state from the unbound server. 125228753Smmget_state ( ) { 126228753Smm # obtain lock for fetching the state 127228753Smm # because there is a race condition in fetching and writing to file 128228753Smm 129228753Smm # see if the lock is stale, if so, take it 130228753Smm if test -f $lock ; then 131228753Smm pid="`cat $lock 2>&1`" 132228753Smm kill -0 "$pid" >/dev/null 2>&1 133228753Smm if test $? -ne 0 -a "$pid" != $$ ; then 134228753Smm echo $$ >$lock 135228753Smm fi 136228753Smm fi 137228753Smm 138228753Smm i=0 139228753Smm while test ! -f $lock || test "`cat $lock 2>&1`" != $$; do 140228753Smm while test -f $lock; do 141228753Smm # wait 142228753Smm i=`expr $i + 1` 143228753Smm if test $i -gt 1000; then 144228753Smm sleep 1; 145228753Smm fi 146228753Smm if test $i -gt 1500; then 147228753Smm echo "error locking $lock" "=" `cat $lock` 148228753Smm rm -f $lock 149228753Smm exit 1 150228753Smm fi 151228753Smm done 152228753Smm # try to get it 153228753Smm if echo $$ >$lock ; then : ; else break; fi 154228753Smm done 155228753Smm # do not refetch if the file exists and only LEE seconds old 156228753Smm if test -f $state; then 157228753Smm now=`date +%s` 158228753Smm get_value "time.now" 159228753Smm value="`echo $value | sed -e 's/\..*$//'`" 160228753Smm if test $now -lt `expr $value + $lee`; then 161228753Smm rm -f $lock 162228753Smm return 163228753Smm fi 164228753Smm fi 165228753Smm $ctrl -c $conf stats > $state 166228753Smm if test $? -ne 0; then 167228753Smm echo "error retrieving data from unbound server" 168228753Smm rm -f $lock 169228753Smm exit 1 170228753Smm fi 171228753Smm rm -f $lock 172228753Smm} 173228753Smm 174228753Smmif test "$1" = "autoconf" ; then 175228753Smm if test ! -f $conf; then 176228753Smm echo no "($conf does not exist)" 177228753Smm exit 1 178228753Smm fi 179228753Smm if test ! -d `dirname $state`; then 180228753Smm echo no "(`dirname $state` directory does not exist)" 181228753Smm exit 1 182228753Smm fi 183228753Smm echo yes 184228753Smm exit 0 185228753Smmfi 186228753Smm 187228753Smmif test "$1" = "suggest" ; then 188228753Smm echo "hits" 189228753Smm echo "queue" 190228753Smm echo "memory" 191228753Smm echo "by_type" 192228753Smm echo "by_class" 193228753Smm echo "by_opcode" 194228753Smm echo "by_rcode" 195228753Smm echo "by_flags" 196228753Smm echo "histogram" 197228753Smm exit 0 198228753Smmfi 199228753Smm 200228753Smm# determine my type, by name 201228753Smmid=`echo $0 | sed -e 's/^.*unbound_munin_//'` 202228753Smmif test "$id"x = ""x; then 203228753Smm # some default to keep people sane. 204228753Smm id="hits" 205228753Smmfi 206228753Smm 207228753Smm# if $1 exists in statefile, config is echoed with label $2 208228753Smmexist_config ( ) { 209228753Smm mn=`echo $1 | sed $ABBREV | tr . _` 210228753Smm if grep '^'$1'=' $state >/dev/null 2>&1; then 211228753Smm echo "$mn.label $2" 212228753Smm echo "$mn.min 0" 213228753Smm echo "$mn.type ABSOLUTE" 214228753Smm fi 215228753Smm} 216228753Smm 217228753Smm# print label and min 0 for a name $1 in unbound format 218228753Smmp_config ( ) { 219228753Smm mn=`echo $1 | sed $ABBREV | tr . _` 220228753Smm echo $mn.label "$2" 221228753Smm echo $mn.min 0 222228753Smm echo $mn.type $3 223228753Smm} 224228753Smm 225228753Smmif test "$1" = "config" ; then 226228753Smm if test ! -f $state; then 227228753Smm get_state 228228753Smm fi 229228753Smm case $id in 230228753Smm hits) 231228753Smm echo "graph_title Unbound DNS traffic and cache hits" 232228753Smm echo "graph_args --base 1000 -l 0" 233228753Smm echo "graph_vlabel queries / \${graph_period}" 234228753Smm echo "graph_scale no" 235228753Smm echo "graph_category DNS" 236228753Smm for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state | 237228753Smm sed -e 's/=.*//'`; do 238228753Smm exist_config $x "queries handled by `basename $x .num.queries`" 239228753Smm done 240228753Smm p_config "total.num.queries" "total queries from clients" "ABSOLUTE" 241228753Smm p_config "total.num.cachehits" "cache hits" "ABSOLUTE" 242228753Smm p_config "total.num.prefetch" "cache prefetch" "ABSOLUTE" 243228753Smm p_config "num.query.tcp" "TCP queries" "ABSOLUTE" 244228753Smm p_config "num.query.tcpout" "TCP out queries" "ABSOLUTE" 245228753Smm p_config "num.query.ipv6" "IPv6 queries" "ABSOLUTE" 246228753Smm p_config "unwanted.queries" "queries that failed acl" "ABSOLUTE" 247228753Smm p_config "unwanted.replies" "unwanted or unsolicited replies" "ABSOLUTE" 248228753Smm echo "u_replies.warning $warn" 249228753Smm echo "u_replies.critical $crit" 250228753Smm echo "graph_info DNS queries to the recursive resolver. The unwanted replies could be innocent duplicate packets, late replies, or spoof threats." 251228753Smm ;; 252228753Smm queue) 253228753Smm echo "graph_title Unbound requestlist size" 254228753Smm echo "graph_args --base 1000 -l 0" 255228753Smm echo "graph_vlabel number of queries" 256228753Smm echo "graph_scale no" 257228753Smm echo "graph_category DNS" 258228753Smm p_config "total.requestlist.avg" "Average size of queue on insert" "GAUGE" 259228753Smm p_config "total.requestlist.max" "Max size of queue (in 5 min)" "GAUGE" 260228753Smm p_config "total.requestlist.overwritten" "Number of queries replaced by new ones" "GAUGE" 261228753Smm p_config "total.requestlist.exceeded" "Number of queries dropped due to lack of space" "GAUGE" 262228753Smm echo "graph_info The queries that did not hit the cache and need recursion service take up space in the requestlist. If there are too many queries, first queries get overwritten, and at last resort dropped." 263228753Smm ;; 264228753Smm memory) 265228753Smm echo "graph_title Unbound memory usage" 266228753Smm echo "graph_args --base 1024 -l 0" 267228753Smm echo "graph_vlabel memory used in bytes" 268228753Smm echo "graph_category DNS" 269228753Smm p_config "mem.cache.rrset" "RRset cache memory" "GAUGE" 270228753Smm p_config "mem.cache.message" "Message cache memory" "GAUGE" 271228753Smm p_config "mem.mod.iterator" "Iterator module memory" "GAUGE" 272228753Smm p_config "mem.mod.validator" "Validator module and key cache memory" "GAUGE" 273228753Smm p_config "msg.cache.count" "msg cache count" "GAUGE" 274228753Smm p_config "rrset.cache.count" "rrset cache count" "GAUGE" 275228753Smm p_config "infra.cache.count" "infra cache count" "GAUGE" 276228753Smm p_config "key.cache.count" "key cache count" "GAUGE" 277228753Smm echo "graph_info The memory used by unbound." 278228753Smm ;; 279228753Smm by_type) 280228753Smm echo "graph_title Unbound DNS queries by type" 281228753Smm echo "graph_args --base 1000 -l 0" 282228753Smm echo "graph_vlabel queries / \${graph_period}" 283228753Smm echo "graph_scale no" 284228753Smm echo "graph_category DNS" 285228753Smm for x in `grep "^num.query.type" $state`; do 286228753Smm nm=`echo $x | sed -e 's/=.*$//'` 287228753Smm tp=`echo $nm | sed -e s/num.query.type.//` 288228753Smm p_config "$nm" "$tp" "ABSOLUTE" 289228753Smm done 290228753Smm echo "graph_info queries by DNS RR type queried for" 291228753Smm ;; 292228753Smm by_class) 293228753Smm echo "graph_title Unbound DNS queries by class" 294228753Smm echo "graph_args --base 1000 -l 0" 295228753Smm echo "graph_vlabel queries / \${graph_period}" 296228753Smm echo "graph_scale no" 297228753Smm echo "graph_category DNS" 298228753Smm for x in `grep "^num.query.class" $state`; do 299228753Smm nm=`echo $x | sed -e 's/=.*$//'` 300228753Smm tp=`echo $nm | sed -e s/num.query.class.//` 301228753Smm p_config "$nm" "$tp" "ABSOLUTE" 302228753Smm done 303228753Smm echo "graph_info queries by DNS RR class queried for." 304228753Smm ;; 305228753Smm by_opcode) 306228753Smm echo "graph_title Unbound DNS queries by opcode" 307228753Smm echo "graph_args --base 1000 -l 0" 308228753Smm echo "graph_vlabel queries / \${graph_period}" 309228753Smm echo "graph_scale no" 310228753Smm echo "graph_category DNS" 311228753Smm for x in `grep "^num.query.opcode" $state`; do 312228753Smm nm=`echo $x | sed -e 's/=.*$//'` 313228753Smm tp=`echo $nm | sed -e s/num.query.opcode.//` 314228753Smm p_config "$nm" "$tp" "ABSOLUTE" 315228753Smm done 316228753Smm echo "graph_info queries by opcode in the query packet." 317228753Smm ;; 318228753Smm by_rcode) 319228753Smm echo "graph_title Unbound DNS answers by return code" 320228753Smm echo "graph_args --base 1000 -l 0" 321228753Smm echo "graph_vlabel answer packets / \${graph_period}" 322228753Smm echo "graph_scale no" 323228753Smm echo "graph_category DNS" 324228753Smm for x in `grep "^num.answer.rcode" $state`; do 325228753Smm nm=`echo $x | sed -e 's/=.*$//'` 326228753Smm tp=`echo $nm | sed -e s/num.answer.rcode.//` 327228753Smm p_config "$nm" "$tp" "ABSOLUTE" 328228753Smm done 329228753Smm p_config "num.answer.secure" "answer secure" "ABSOLUTE" 330228753Smm p_config "num.answer.bogus" "answer bogus" "ABSOLUTE" 331228753Smm p_config "num.rrset.bogus" "num rrsets marked bogus" "ABSOLUTE" 332228753Smm echo "graph_info answers sorted by return value. rrsets bogus is the number of rrsets marked bogus per \${graph_period} by the validator" 333228753Smm ;; 334228753Smm by_flags) 335228753Smm echo "graph_title Unbound DNS incoming queries by flags" 336228753Smm echo "graph_args --base 1000 -l 0" 337228753Smm echo "graph_vlabel queries / \${graph_period}" 338228753Smm echo "graph_scale no" 339228753Smm echo "graph_category DNS" 340228753Smm p_config "num.query.flags.QR" "QR (query reply) flag" "ABSOLUTE" 341228753Smm p_config "num.query.flags.AA" "AA (auth answer) flag" "ABSOLUTE" 342228753Smm p_config "num.query.flags.TC" "TC (truncated) flag" "ABSOLUTE" 343228753Smm p_config "num.query.flags.RD" "RD (recursion desired) flag" "ABSOLUTE" 344228753Smm p_config "num.query.flags.RA" "RA (rec avail) flag" "ABSOLUTE" 345228753Smm p_config "num.query.flags.Z" "Z (zero) flag" "ABSOLUTE" 346228753Smm p_config "num.query.flags.AD" "AD (auth data) flag" "ABSOLUTE" 347228753Smm p_config "num.query.flags.CD" "CD (check disabled) flag" "ABSOLUTE" 348228753Smm p_config "num.query.edns.present" "EDNS OPT present" "ABSOLUTE" 349228753Smm p_config "num.query.edns.DO" "DO (DNSSEC OK) flag" "ABSOLUTE" 350228753Smm echo "graph_info This graphs plots the flags inside incoming queries. For example, if QR, AA, TC, RA, Z flags are set, the query can be rejected. RD, AD, CD and DO are legitimately set by some software." 351228753Smm ;; 352228753Smm histogram) 353228753Smm echo "graph_title Unbound DNS histogram of reply time" 354228753Smm echo "graph_args --base 1000 -l 0" 355228753Smm echo "graph_vlabel queries / \${graph_period}" 356228753Smm echo "graph_scale no" 357228753Smm echo "graph_category DNS" 358228753Smm echo hcache.label "cache hits" 359228753Smm echo hcache.min 0 360228753Smm echo hcache.type ABSOLUTE 361228753Smm echo hcache.draw AREA 362228753Smm echo hcache.colour 999999 363228753Smm echo h64ms.label "0 msec - 66 msec" 364228753Smm echo h64ms.min 0 365228753Smm echo h64ms.type ABSOLUTE 366228753Smm echo h64ms.draw STACK 367228753Smm echo h64ms.colour 0000FF 368228753Smm echo h128ms.label "66 msec - 131 msec" 369228753Smm echo h128ms.min 0 370228753Smm echo h128ms.type ABSOLUTE 371228753Smm echo h128ms.colour 1F00DF 372228753Smm echo h128ms.draw STACK 373228753Smm echo h256ms.label "131 msec - 262 msec" 374228753Smm echo h256ms.min 0 375228753Smm echo h256ms.type ABSOLUTE 376228753Smm echo h256ms.draw STACK 377228753Smm echo h256ms.colour 3F00BF 378228753Smm echo h512ms.label "262 msec - 524 msec" 379228753Smm echo h512ms.min 0 380228753Smm echo h512ms.type ABSOLUTE 381228753Smm echo h512ms.draw STACK 382228753Smm echo h512ms.colour 5F009F 383228753Smm echo h1s.label "524 msec - 1 sec" 384228753Smm echo h1s.min 0 385228753Smm echo h1s.type ABSOLUTE 386228753Smm echo h1s.draw STACK 387228753Smm echo h1s.colour 7F007F 388228753Smm echo h2s.label "1 sec - 2 sec" 389228753Smm echo h2s.min 0 390228753Smm echo h2s.type ABSOLUTE 391228753Smm echo h2s.draw STACK 392228753Smm echo h2s.colour 9F005F 393228753Smm echo h4s.label "2 sec - 4 sec" 394228753Smm echo h4s.min 0 395228753Smm echo h4s.type ABSOLUTE 396228753Smm echo h4s.draw STACK 397228753Smm echo h4s.colour BF003F 398228753Smm echo h8s.label "4 sec - 8 sec" 399228753Smm echo h8s.min 0 400228753Smm echo h8s.type ABSOLUTE 401228753Smm echo h8s.draw STACK 402228753Smm echo h8s.colour DF001F 403228753Smm echo h16s.label "8 sec - ..." 404228753Smm echo h16s.min 0 405228753Smm echo h16s.type ABSOLUTE 406228753Smm echo h16s.draw STACK 407228753Smm echo h16s.colour FF0000 408228753Smm echo "graph_info Histogram of the reply times for queries." 409228753Smm ;; 410228753Smm esac 411228753Smm 412228753Smm exit 0 413228753Smmfi 414228753Smm 415228753Smm# do the stats itself 416228753Smmget_state 417228753Smm 418228753Smm# get the time elapsed 419228753Smmget_value "time.elapsed" 420228753Smmif test $value = 0 || test $value = "0.000000"; then 421228753Smm echo "error: time elapsed 0 or could not retrieve data" 422228753Smm exit 1 423228753Smmfi 424228753Smmelapsed="$value" 425228753Smm 426228753Smm# print value for $1 427228753Smmprint_value ( ) { 428228753Smm mn=`echo $1 | sed $ABBREV | tr . _` 429228753Smm get_value $1 430228753Smm echo "$mn.value" $value 431228753Smm} 432228753Smm 433228753Smm# print value if line already found in $2 434228753Smmprint_value_line ( ) { 435228753Smm mn=`echo $1 | sed $ABBREV | tr . _` 436228753Smm value="`echo $2 | sed -e 's/^.*=//'`" 437228753Smm echo "$mn.value" $value 438228753Smm} 439228753Smm 440228753Smm 441228753Smmcase $id in 442228753Smmhits) 443228753Smm for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state | 444228753Smm sed -e 's/=.*//'` total.num.queries \ 445228753Smm total.num.cachehits total.num.prefetch num.query.tcp \ 446228753Smm num.query.tcpout num.query.ipv6 unwanted.queries \ 447228753Smm unwanted.replies; do 448228753Smm if grep "^"$x"=" $state >/dev/null 2>&1; then 449228753Smm print_value $x 450228753Smm fi 451228753Smm done 452228753Smm ;; 453228753Smmqueue) 454228753Smm for x in total.requestlist.avg total.requestlist.max \ 455228753Smm total.requestlist.overwritten total.requestlist.exceeded; do 456228753Smm print_value $x 457228753Smm done 458228753Smm ;; 459228753Smmmemory) 460228753Smm for x in mem.cache.rrset mem.cache.message mem.mod.iterator \ 461228753Smm mem.mod.validator msg.cache.count rrset.cache.count \ 462228753Smm infra.cache.count key.cache.count; do 463228753Smm print_value $x 464228753Smm done 465228753Smm ;; 466228753Smmby_type) 467228753Smm for x in `grep "^num.query.type" $state`; do 468228753Smm nm=`echo $x | sed -e 's/=.*$//'` 469228753Smm print_value_line $nm $x 470228753Smm done 471228753Smm ;; 472228753Smmby_class) 473228753Smm for x in `grep "^num.query.class" $state`; do 474228753Smm nm=`echo $x | sed -e 's/=.*$//'` 475228753Smm print_value_line $nm $x 476228753Smm done 477228753Smm ;; 478228753Smmby_opcode) 479228753Smm for x in `grep "^num.query.opcode" $state`; do 480228753Smm nm=`echo $x | sed -e 's/=.*$//'` 481228753Smm print_value_line $nm $x 482228753Smm done 483228753Smm ;; 484228753Smmby_rcode) 485228753Smm for x in `grep "^num.answer.rcode" $state`; do 486228753Smm nm=`echo $x | sed -e 's/=.*$//'` 487228753Smm print_value_line $nm $x 488228753Smm done 489228753Smm print_value "num.answer.secure" 490228753Smm print_value "num.answer.bogus" 491228753Smm print_value "num.rrset.bogus" 492228753Smm ;; 493228753Smmby_flags) 494228753Smm for x in num.query.flags.QR num.query.flags.AA num.query.flags.TC num.query.flags.RD num.query.flags.RA num.query.flags.Z num.query.flags.AD num.query.flags.CD num.query.edns.present num.query.edns.DO; do 495228753Smm print_value $x 496228753Smm done 497228753Smm ;; 498228753Smmhistogram) 499228753Smm get_value total.num.cachehits 500228753Smm echo hcache.value $value 501228753Smm r=0 502228753Smm for x in histogram.000000.000000.to.000000.000001 \ 503228753Smm histogram.000000.000001.to.000000.000002 \ 504228753Smm histogram.000000.000002.to.000000.000004 \ 505228753Smm histogram.000000.000004.to.000000.000008 \ 506228753Smm histogram.000000.000008.to.000000.000016 \ 507228753Smm histogram.000000.000016.to.000000.000032 \ 508228753Smm histogram.000000.000032.to.000000.000064 \ 509228753Smm histogram.000000.000064.to.000000.000128 \ 510228753Smm histogram.000000.000128.to.000000.000256 \ 511228753Smm histogram.000000.000256.to.000000.000512 \ 512228753Smm histogram.000000.000512.to.000000.001024 \ 513228753Smm histogram.000000.001024.to.000000.002048 \ 514228753Smm histogram.000000.002048.to.000000.004096 \ 515228753Smm histogram.000000.004096.to.000000.008192 \ 516228753Smm histogram.000000.008192.to.000000.016384 \ 517228753Smm histogram.000000.016384.to.000000.032768 \ 518228753Smm histogram.000000.032768.to.000000.065536; do 519228753Smm get_value $x 520228753Smm r=`expr $r + $value` 521228753Smm done 522228753Smm echo h64ms.value $r 523228753Smm get_value histogram.000000.065536.to.000000.131072 524228753Smm echo h128ms.value $value 525228753Smm get_value histogram.000000.131072.to.000000.262144 526228753Smm echo h256ms.value $value 527228753Smm get_value histogram.000000.262144.to.000000.524288 528228753Smm echo h512ms.value $value 529228753Smm get_value histogram.000000.524288.to.000001.000000 530228753Smm echo h1s.value $value 531228753Smm get_value histogram.000001.000000.to.000002.000000 532228753Smm echo h2s.value $value 533228753Smm get_value histogram.000002.000000.to.000004.000000 534228753Smm echo h4s.value $value 535228753Smm get_value histogram.000004.000000.to.000008.000000 536228753Smm echo h8s.value $value 537228753Smm r=0 538228753Smm for x in histogram.000008.000000.to.000016.000000 \ 539228753Smm histogram.000016.000000.to.000032.000000 \ 540228753Smm histogram.000032.000000.to.000064.000000 \ 541228753Smm histogram.000064.000000.to.000128.000000 \ 542228753Smm histogram.000128.000000.to.000256.000000 \ 543228753Smm histogram.000256.000000.to.000512.000000 \ 544228753Smm histogram.000512.000000.to.001024.000000 \ 545228753Smm histogram.001024.000000.to.002048.000000 \ 546228753Smm histogram.002048.000000.to.004096.000000 \ 547228753Smm histogram.004096.000000.to.008192.000000 \ 548228753Smm histogram.008192.000000.to.016384.000000 \ 549228753Smm histogram.016384.000000.to.032768.000000 \ 550228753Smm histogram.032768.000000.to.065536.000000 \ 551228753Smm histogram.065536.000000.to.131072.000000 \ 552228753Smm histogram.131072.000000.to.262144.000000 \ 553228753Smm histogram.262144.000000.to.524288.000000; do 554228753Smm get_value $x 555228753Smm r=`expr $r + $value` 556228753Smm done 557228753Smm echo h16s.value $r 558228753Smm ;; 559228753Smmesac 560228753Smm