Counters::inc() now takes DNS message and query/response attributes.
It increments the counters related to the message.
Some tests have been mofdified or removedue to the change of the
interface.
"item_type": "integer",
"item_optional": false,
"item_default": 0,
- "item_title": "Queries TCP ",
+ "item_title": "Queries TCP",
"item_description": "A number of total query counts which all auth servers receive over TCP since they started initially"
},
{
"item_title": "Received status requests",
"item_description": "The number of total request counts whose opcode is status"
},
- {
- "item_name": "opcode.reserved3",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 3",
- "item_description": "The number of total request counts whose opcode is 3 (reserved)"
- },
{
"item_name": "opcode.notify",
"item_type": "integer",
"item_description": "The number of total request counts whose opcode is update"
},
{
- "item_name": "opcode.reserved6",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 6",
- "item_description": "The number of total request counts whose opcode is 6 (reserved)"
- },
- {
- "item_name": "opcode.reserved7",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 7",
- "item_description": "The number of total request counts whose opcode is 7 (reserved)"
- },
- {
- "item_name": "opcode.reserved8",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 8",
- "item_description": "The number of total request counts whose opcode is 8 (reserved)"
- },
- {
- "item_name": "opcode.reserved9",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 9",
- "item_description": "The number of total request counts whose opcode is 9 (reserved)"
- },
- {
- "item_name": "opcode.reserved10",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 10",
- "item_description": "The number of total request counts whose opcode is 10 (reserved)"
- },
- {
- "item_name": "opcode.reserved11",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 11",
- "item_description": "The number of total request counts whose opcode is 11 (reserved)"
- },
- {
- "item_name": "opcode.reserved12",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 12",
- "item_description": "The number of total request counts whose opcode is 12 (reserved)"
- },
- {
- "item_name": "opcode.reserved13",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 13",
- "item_description": "The number of total request counts whose opcode is 13 (reserved)"
- },
- {
- "item_name": "opcode.reserved14",
- "item_type": "integer",
- "item_optional": true,
- "item_default": 0,
- "item_title": "Received requests opcode 14",
- "item_description": "The number of total request counts whose opcode is 14 (reserved)"
- },
- {
- "item_name": "opcode.reserved15",
+ "item_name": "opcode.other",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
- "item_title": "Received requests opcode 15",
- "item_description": "The number of total request counts whose opcode is 15 (reserved)"
+ "item_title": "Received requests opcode other",
+ "item_description": "The number of total request counts whose opcode is other (not well-known)"
},
{
"item_name": "rcode.noerror",
"item_description": "The number of total responses with rcode 10 (NOTZONE)"
},
{
- "item_name": "rcode.reserved11",
+ "item_name": "rcode.badsigvers",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
- "item_title": "Sent response with rcode 11",
- "item_description": "The number of total responses with rcode 11 (reserved)"
+ "item_title": "Sent 'EDNS version not implemented' response",
+ "item_description": "The number of total responses with rcode 16 (BADVERS)"
},
{
- "item_name": "rcode.reserved12",
+ "item_name": "rcode.badkey",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
- "item_title": "Sent response with rcode 12",
- "item_description": "The number of total responses with rcode 12 (reserved)"
+ "item_title": "Sent 'Key not recognized' response",
+ "item_description": "The number of total responses with rcode 17 (BADKEY)"
},
{
- "item_name": "rcode.reserved13",
+ "item_name": "rcode.badtime",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
- "item_title": "Sent response with rcode 13",
- "item_description": "The number of total responses with rcode 13 (reserved)"
+ "item_title": "Sent 'Signature out of time window' response",
+ "item_description": "The number of total responses with rcode 18 (BADTIME)"
},
{
- "item_name": "rcode.reserved14",
+ "item_name": "rcode.badmode",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
- "item_title": "Sent response with rcode 14",
- "item_description": "The number of total responses with rcode 14 (reserved)"
+ "item_title": "Sent 'Bad TKEY Mode' response",
+ "item_description": "The number of total responses with rcode 19 (BADMODE)"
},
{
- "item_name": "rcode.reserved15",
+ "item_name": "rcode.badname",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
- "item_title": "Sent response with rcode 15",
- "item_description": "The number of total responses with rcode 15 (reserved)"
+ "item_title": "Sent 'Duplicate key name' response",
+ "item_description": "The number of total responses with rcode 20 (BADNAME)"
},
{
- "item_name": "rcode.badvers",
+ "item_name": "rcode.badalg",
"item_type": "integer",
"item_optional": true,
"item_default": 0,
- "item_title": "Sent 'EDNS version not implemented' response",
- "item_description": "The number of total responses with rcode 16 (BADVERS)"
+ "item_title": "Sent 'Algorithm not supported' response",
+ "item_description": "The number of total responses with rcode 21 (BADALG)"
+ },
+ {
+ "item_name": "rcode.badtrunc",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Sent 'Bad Truncation' response",
+ "item_description": "The number of total responses with rcode 22 (BADTRUNC)"
+ },
+ {
+ "item_name": "rcode.other",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Sent responses with rcode other",
+ "item_description": "The number of total responses with rcode other (not well-known)"
}
]
}
/// \brief Resume the server
///
- /// This is a wrapper call for DNSServer::resume(done), if 'done' is true,
- /// the Rcode set in the given Message is counted in the statistics
- /// counter.
+ /// This is a wrapper call for DNSServer::resume(done). Query/Response
+ /// statistics counters are incremented in this method.
///
/// This method is expected to be called by processMessage()
///
/// \param server The DNSServer as passed to processMessage()
/// \param message The response as constructed by processMessage()
- /// \param done If true, the Rcode from the given message is counted,
- /// this value is then passed to server->resume(bool)
+ /// \param stats_attrs Query/response attributes for statistics which is
+ /// not in \p messsage.
+ /// Note: This parameter is modified inside this method
+ /// to store whether the answer has been sent and
+ /// the response is truncated.
+ /// \param done If true, it indicates there is a response.
+ /// this value will be passed to server->resume(bool)
void resumeServer(isc::asiodns::DNSServer* server,
isc::dns::Message& message,
- bool done);
+ statistics::QRAttributes& stats_attrs,
+ const bool done);
private:
bool xfrout_connected_;
AbstractXfroutClient& xfrout_client_;
- /// Increment query counter
- void incCounter(const int protocol);
-
// validateStatistics
bool validateStatistics(isc::data::ConstElementPtr data) const;
OutputBuffer& buffer, DNSServer* server)
{
InputBuffer request_buffer(io_message.getData(), io_message.getDataSize());
+ statistics::QRAttributes stats_attrs;
+
+ // statistics: check transport carrying the message (IP, transport)
+ stats_attrs.setQueryIPVersion(io_message.getRemoteEndpoint().getFamily());
+ stats_attrs.setQueryTransportProtocol(
+ io_message.getRemoteEndpoint().getProtocol());
// First, check the header part. If we fail even for the base header,
// just drop the message.
// Ignore all responses.
if (message.getHeaderFlag(Message::HEADERFLAG_QR)) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_RECEIVED);
- impl_->resumeServer(server, message, false);
+ impl_->resumeServer(server, message, stats_attrs, false);
return;
}
} catch (const Exception& ex) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_HEADER_PARSE_FAIL)
.arg(ex.what());
- impl_->resumeServer(server, message, false);
+ impl_->resumeServer(server, message, stats_attrs, false);
return;
}
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PROTOCOL_ERROR)
.arg(error.getRcode().toText()).arg(error.what());
makeErrorMessage(impl_->renderer_, message, buffer, error.getRcode());
- impl_->resumeServer(server, message, true);
+ impl_->resumeServer(server, message, stats_attrs, true);
return;
} catch (const Exception& ex) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_PACKET_PARSE_ERROR)
.arg(ex.what());
makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
- impl_->resumeServer(server, message, true);
+ impl_->resumeServer(server, message, stats_attrs, true);
return;
} // other exceptions will be handled at a higher layer.
**impl_->keyring_));
tsig_error = tsig_context->verify(tsig_record, io_message.getData(),
io_message.getDataSize());
+ // statistics: check TSIG attributes
+ // SIG(0) is currently not implemented in Auth
+ stats_attrs.setQuerySig(true, false,
+ tsig_error == TSIGError::NOERROR());
}
if (tsig_error != TSIGError::NOERROR()) {
makeErrorMessage(impl_->renderer_, message, buffer,
tsig_error.toRcode(), tsig_context);
- impl_->resumeServer(server, message, true);
+ impl_->resumeServer(server, message, stats_attrs, true);
return;
}
const Opcode opcode = message.getOpcode();
bool send_answer = true;
try {
- // update per opcode statistics counter. This can only be reliable
- // after TSIG check succeeds.
- impl_->counters_.inc(message.getOpcode());
+ // statistics: check EDNS
+ // note: This can only be reliable after TSIG check succeeds.
+ {
+ ConstEDNSPtr edns = message.getEDNS();
+ if (edns != NULL) {
+ stats_attrs.setQueryEDNS(true, edns->getVersion() == 0);
+ stats_attrs.setQueryDO(edns->getDNSSECAwareness());
+ }
+ }
+
+ // statistics: check OpCode
+ // note: This can only be reliable after TSIG check succeeds.
+ stats_attrs.setQueryOpCode(opcode.getCode());
if (opcode == Opcode::NOTIFY()) {
send_answer = impl_->processNotify(io_message, message, buffer,
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_RESPONSE_FAILURE_UNKNOWN);
makeErrorMessage(impl_->renderer_, message, buffer, Rcode::SERVFAIL());
}
- impl_->resumeServer(server, message, send_answer);
+ impl_->resumeServer(server, message, stats_attrs, send_answer);
}
bool
message.setHeaderFlag(Message::HEADERFLAG_AA);
message.setRcode(Rcode::NOERROR());
- // Increment query counter.
- incCounter(io_message.getSocket().getProtocol());
-
if (remote_edns) {
EDNSPtr local_edns = EDNSPtr(new EDNS());
local_edns->setDNSSECAwareness(dnssec_ok);
OutputBuffer& buffer,
auto_ptr<TSIGContext> tsig_context)
{
- // Increment query counter.
- incCounter(io_message.getSocket().getProtocol());
-
if (io_message.getSocket().getProtocol() == IPPROTO_UDP) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_AXFR_UDP);
makeErrorMessage(renderer_, message, buffer, Rcode::FORMERR(),
return (false);
}
-void
-AuthSrvImpl::incCounter(const int protocol) {
- // Increment query counter.
- if (protocol == IPPROTO_UDP) {
- counters_.inc(Counters::SERVER_UDP_QUERY);
- } else if (protocol == IPPROTO_TCP) {
- counters_.inc(Counters::SERVER_TCP_QUERY);
- } else {
- // unknown protocol
- isc_throw(Unexpected, "Unknown protocol: " << protocol);
- }
-}
-
void
AuthSrvImpl::registerStatisticsValidator() {
counters_.registerStatisticsValidator(
}
void
-AuthSrvImpl::resumeServer(DNSServer* server, Message& message, bool done) {
+AuthSrvImpl::resumeServer(DNSServer* server, Message& message,
+ statistics::QRAttributes& stats_attrs,
+ const bool done) {
if (done) {
- counters_.inc(message.getRcode());
+ stats_attrs.answerWasSent();
+ // isTruncated from MessageRenderer
+ stats_attrs.setResponseTruncated(renderer_.isTruncated());
}
+ counters_.inc(stats_attrs, message);
server->resume(done);
}
return (impl_->counters_.getStatistics());
}
-uint64_t
-AuthSrv::getCounter(const Counters::ServerCounterType type) const {
- return (impl_->counters_.getCounter(type));
-}
-
-uint64_t
-AuthSrv::getCounter(const Opcode opcode) const {
- return (impl_->counters_.getCounter(opcode));
-}
-
-uint64_t
-AuthSrv::getCounter(const Rcode rcode) const {
- return (impl_->counters_.getCounter(rcode));
-}
-
const AddressList&
AuthSrv::getListenAddresses() const {
return (impl_->listen_addresses_);
/// \return JSON format statistics data.
isc::data::ConstElementPtr getStatistics() const;
- /// \brief Get the value of counter in the Counters.
- ///
- /// This function calls Counters::getStatistics() and
- /// returns its return value.
- ///
- /// This function never throws an exception as far as
- /// Counters::getStatistics() doesn't throw.
- ///
- /// Note: Currently this function is for testing purpose only.
- ///
- /// \param type Type of a counter to get the value of
- ///
- /// \return the value of the counter.
-
- uint64_t getCounter(
- const isc::auth::statistics::Counters::ServerCounterType type)
- const;
-
- /// \brief Get the value of per Opcode counter in the Auth Counters.
- ///
- /// This function calls Counters::getCounter(isc::dns::Opcode) and
- /// returns its return value.
- ///
- /// \note This is a tentative interface as an attempt of experimentally
- /// supporting more statistics counters. This should eventually be more
- /// generalized. In any case, this method is mainly for testing.
- ///
- /// \throw None
- /// \param opcode The opcode of the counter to get the value of
- /// \return the value of the counter.
- uint64_t getCounter(const isc::dns::Opcode opcode) const;
-
- /// \brief Get the value of per Rcode counter in the Auth Counters.
- ///
- /// This function calls Counters::getCounter(isc::dns::Rcode) and
- /// returns its return value.
- ///
- /// \note This is a tentative interface as an attempt of experimentally
- /// supporting more statistics counters. This should eventually be more
- /// generalized. In any case, this method is mainly for testing.
- ///
- /// \throw None
- /// \param rcode The rcode of the counter to get the value of
- /// \return the value of the counter.
- uint64_t getCounter(const isc::dns::Rcode rcode) const;
-
/**
* \brief Set and get the addresses we listen on.
*/
// PERFORMANCE OF THIS SOFTWARE.
#include <auth/statistics.h>
+#include <auth/statistics_items.h>
#include <auth/auth_log.h>
#include <dns/opcode.h>
+#include <dns/rcode.h>
#include <cc/data.h>
#include <cc/session.h>
#include <boost/noncopyable.hpp>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
using namespace isc::dns;
using namespace isc::auth;
using namespace isc::statistics;
public:
CountersImpl();
~CountersImpl();
- void inc(const Counters::ServerCounterType type);
- void inc(const Opcode opcode) {
- opcode_counter_.inc(opcode.getCode());
- }
- void inc(const Rcode rcode) {
- rcode_counter_.inc(rcode.getCode());
- }
- void inc(const std::string& zone, const Counters::PerZoneCounterType type);
+ void inc(const QRAttributes& qrattrs, const Message& response);
isc::data::ConstElementPtr getStatistics() const;
- void registerStatisticsValidator (Counters::validator_type validator);
- // Currently for testing purpose only
- uint64_t getCounter(const Counters::ServerCounterType type) const;
- uint64_t getCounter(const Opcode opcode) const {
- return (opcode_counter_.get(opcode.getCode()));
- }
- uint64_t getCounter(const Rcode rcode) const {
- return (rcode_counter_.get(rcode.getCode()));
- }
+ void registerStatisticsValidator(Counters::validator_type validator);
private:
- Counter server_counter_;
- Counter opcode_counter_;
- static const size_t NUM_OPCODES = 16;
- Counter rcode_counter_;
- static const size_t NUM_RCODES = 17;
- CounterDictionary per_zone_counter_;
+ // counter for query/response
+ Counter server_qr_counter_;
+ // counter for socket
+ Counter socket_counter_;
+ // set of counters for zones
+ CounterDictionary zone_qr_counters_;
+ // validator
Counters::validator_type validator_;
};
CountersImpl::CountersImpl() :
- // initialize counter
- // size of server_counter_: Counters::SERVER_COUNTER_TYPES
- // size of per_zone_counter_: Counters::PER_ZONE_COUNTER_TYPES
- server_counter_(Counters::SERVER_COUNTER_TYPES),
- opcode_counter_(NUM_OPCODES), rcode_counter_(NUM_RCODES),
- per_zone_counter_(Counters::PER_ZONE_COUNTER_TYPES)
-{
- per_zone_counter_.addElement("_SERVER_");
-}
+ // size of server_qr_counter_, zone_qr_counters_: QR_COUNTER_TYPES
+ // size of server_socket_counter_: SOCKET_COUNTER_TYPES
+ server_qr_counter_(QR_COUNTER_TYPES),
+ socket_counter_(SOCKET_COUNTER_TYPES),
+ zone_qr_counters_(QR_COUNTER_TYPES),
+ validator_()
+{}
CountersImpl::~CountersImpl()
{}
void
-CountersImpl::inc(const Counters::ServerCounterType type) {
- server_counter_.inc(type);
-}
+CountersImpl::inc(const QRAttributes& qrattrs, const Message& response) {
+ // protocols carrying request
+ if (qrattrs.req_ip_version_ == AF_INET) {
+ server_qr_counter_.inc(QR_REQUEST_IPV4);
+ } else if (qrattrs.req_ip_version_ == AF_INET6) {
+ server_qr_counter_.inc(QR_REQUEST_IPV6);
+ }
+ if (qrattrs.req_transport_protocol_ == IPPROTO_UDP) {
+ server_qr_counter_.inc(QR_REQUEST_UDP);
+ } else if (qrattrs.req_transport_protocol_ == IPPROTO_TCP) {
+ server_qr_counter_.inc(QR_REQUEST_TCP);
+ }
-void
-CountersImpl::inc(const std::string& zone,
- const Counters::PerZoneCounterType type)
-{
- per_zone_counter_[zone].inc(type);
+ // query TSIG
+ if (qrattrs.req_is_tsig_) {
+ server_qr_counter_.inc(QR_REQUEST_TSIG);
+ }
+ if (qrattrs.req_is_sig0_) {
+ server_qr_counter_.inc(QR_REQUEST_SIG0);
+ }
+ if (qrattrs.req_is_badsig_) {
+ server_qr_counter_.inc(QR_REQUEST_BADSIG);
+ // If signature validation is failed, no other attributes are reliable
+ return;
+ }
+
+ // query EDNS
+ if (qrattrs.req_is_edns_0_) {
+ server_qr_counter_.inc(QR_REQUEST_EDNS0);
+ }
+ if (qrattrs.req_is_edns_badver_) {
+ server_qr_counter_.inc(QR_REQUEST_BADEDNSVER);
+ }
+
+ // query DNSSEC
+ if (qrattrs.req_is_dnssec_ok_) {
+ server_qr_counter_.inc(QR_REQUEST_DNSSEC_OK);
+ }
+
+ // QTYPE
+ unsigned int qtype_type = QR_QTYPE_OTHER;
+ const QuestionIterator qiter = response.beginQuestion();
+ if (qiter != response.endQuestion()) {
+ // get the first and only question section
+ const QuestionPtr qptr = *qiter;
+ if (qptr != NULL) {
+ // get the qtype code
+ const unsigned int qtype = qptr->getType().getCode();
+ if (qtype < 258) {
+ // qtype 0..257
+ qtype_type = QRQTypeToQRCounterType[qtype];
+ } else if (qtype < 32768) {
+ // qtype 258..32767
+ qtype_type = QR_QTYPE_OTHER;
+ } else if (qtype < 32770) {
+ // qtype 32768..32769
+ qtype_type = QR_QTYPE_TA + (qtype - 32768);
+ } else {
+ // qtype 32770..65535
+ qtype_type = QR_QTYPE_OTHER;
+ }
+ }
+ }
+ server_qr_counter_.inc(qtype_type);
+ // OPCODE
+ server_qr_counter_.inc(QROpCodeToQRCounterType[qrattrs.req_opcode_]);
+
+ // response
+ if (qrattrs.answer_sent_) {
+ // responded
+ server_qr_counter_.inc(QR_RESPONSE);
+
+ // response truncated
+ if (qrattrs.res_is_truncated_) {
+ server_qr_counter_.inc(QR_RESPONSE_TRUNCATED);
+ }
+
+ // response EDNS
+ ConstEDNSPtr response_edns = response.getEDNS();
+ if (response_edns != NULL && response_edns->getVersion() == 0) {
+ server_qr_counter_.inc(QR_RESPONSE_EDNS0);
+ }
+
+ // response TSIG
+ if (qrattrs.req_is_tsig_) {
+ // assume response is TSIG signed if request is TSIG signed
+ server_qr_counter_.inc(QR_RESPONSE_TSIG);
+ }
+
+ // response SIG(0) is currently not implemented
+
+ // RCODE
+ const unsigned int rcode = response.getRcode().getCode();
+ unsigned int rcode_type = QR_RCODE_OTHER;
+ if (rcode < 23) {
+ // rcode 0..22
+ rcode_type = QRRCodeToQRCounterType[rcode];
+ } else {
+ // opcode larger than 22 is reserved or unassigned
+ rcode_type = QR_RCODE_OTHER;
+ }
+ server_qr_counter_.inc(rcode_type);
+
+ // compound attributes
+ const unsigned int answer_rrs =
+ response.getRRCount(Message::SECTION_ANSWER);
+ const bool is_aa_set = response.getHeaderFlag(Message::HEADERFLAG_AA);
+
+ if (is_aa_set) {
+ // QryAuthAns
+ server_qr_counter_.inc(QR_QRYAUTHANS);
+ } else {
+ // QryNoAuthAns
+ server_qr_counter_.inc(QR_QRYNOAUTHANS);
+ }
+
+ if (rcode == Rcode::NOERROR_CODE) {
+ if (answer_rrs > 0) {
+ // QrySuccess
+ server_qr_counter_.inc(QR_QRYSUCCESS);
+ } else {
+ if (is_aa_set) {
+ // QryNxrrset
+ server_qr_counter_.inc(QR_QRYNXRRSET);
+ } else {
+ // QryReferral
+ server_qr_counter_.inc(QR_QRYREFERRAL);
+ }
+ }
+ } else if (rcode == Rcode::REFUSED_CODE) {
+ // AuthRej
+ server_qr_counter_.inc(QR_QRYREJECT);
+ }
+ }
}
isc::data::ConstElementPtr
CountersImpl::getStatistics() const {
std::stringstream statistics_string;
statistics_string << "{ \"queries.udp\": "
- << server_counter_.get(Counters::SERVER_UDP_QUERY)
+ << server_qr_counter_.get(QR_REQUEST_UDP)
<< ", \"queries.tcp\": "
- << server_counter_.get(Counters::SERVER_TCP_QUERY);
+ << server_qr_counter_.get(QR_REQUEST_TCP);
// Insert non 0 Opcode counters.
- for (int i = 0; i < NUM_OPCODES; ++i) {
- const Counter::Type counter = opcode_counter_.get(i);
+ for (int i = QR_OPCODE_QUERY; i <= QR_OPCODE_OTHER; ++i) {
+ const Counter::Type counter = server_qr_counter_.get(i);
if (counter != 0) {
- // The counter item name should be derived lower-cased textual
- // representation of the code.
- std::string opcode_txt = Opcode(i).toText();
- std::transform(opcode_txt.begin(), opcode_txt.end(),
- opcode_txt.begin(), ::tolower);
- statistics_string << ", \"opcode." << opcode_txt << "\": "
+ statistics_string << ", \"" << QRCounterItemName[i] << "\": "
<< counter;
}
}
// Insert non 0 Rcode counters.
- for (int i = 0; i < NUM_RCODES; ++i) {
- const Counter::Type counter = rcode_counter_.get(i);
+ for (int i = QR_RCODE_NOERROR; i <= QR_RCODE_OTHER; ++i) {
+ const Counter::Type counter = server_qr_counter_.get(i);
if (counter != 0) {
- // The counter item name should be derived lower-cased textual
- // representation of the code.
- std::string rcode_txt = Rcode(i).toText();
- std::transform(rcode_txt.begin(), rcode_txt.end(),
- rcode_txt.begin(), ::tolower);
- statistics_string << ", \"rcode." << rcode_txt << "\": "
+ statistics_string << ", \"" << QRCounterItemName[i] << "\": "
<< counter;
}
}
validator_ = validator;
}
-// Currently for testing purpose only
-uint64_t
-CountersImpl::getCounter(const Counters::ServerCounterType type) const {
- return (server_counter_.get(type));
-}
-
Counters::Counters() : impl_(new CountersImpl())
{}
Counters::~Counters() {}
void
-Counters::inc(const Counters::ServerCounterType type) {
- impl_->inc(type);
-}
-
-void
-Counters::inc(const Opcode opcode) {
- impl_->inc(opcode);
-}
-
-void
-Counters::inc(const Rcode rcode) {
- impl_->inc(rcode);
+Counters::inc(const QRAttributes& qrattrs, const Message& response) {
+ impl_->inc(qrattrs, response);
}
isc::data::ConstElementPtr
return (impl_->getStatistics());
}
-uint64_t
-Counters::getCounter(const Counters::ServerCounterType type) const {
- return (impl_->getCounter(type));
-}
-
-uint64_t
-Counters::getCounter(const Opcode opcode) const {
- return (impl_->getCounter(opcode));
-}
-
-uint64_t
-Counters::getCounter(const Rcode rcode) const {
- return (impl_->getCounter(rcode));
-}
-
void
Counters::registerStatisticsValidator
(Counters::validator_type validator) const
#ifndef __STATISTICS_H
#define __STATISTICS_H 1
-#include <dns/opcode.h>
-#include <dns/rcode.h>
#include <cc/session.h>
#include <cc/data.h>
+#include <dns/message.h>
+
+#include <string>
+
#include <stdint.h>
#include <boost/scoped_ptr.hpp>
/// statistics module.
///
/// This class is designed to be a part of \c AuthSrv.
-/// Call \c inc() to increment a counter for specific type of query in
-/// the query processing function. use \c enum \c CounterType to specify
-/// the type of query.
+/// Call \c inc() to increment a counter for the query.
/// Call \c getStatistics() to answer statistics information to statistics
/// module with statistics_session, when the command \c getstats is received.
///
private:
boost::scoped_ptr<CountersImpl> impl_;
public:
- // Enum for the type of counter
- enum ServerCounterType {
- SERVER_UDP_QUERY, ///< SERVER_UDP_QUERY: counter for UDP queries
- SERVER_TCP_QUERY, ///< SERVER_TCP_QUERY: counter for TCP queries
- SERVER_COUNTER_TYPES ///< The number of defined counters
- };
- enum PerZoneCounterType {
- ZONE_UDP_QUERY, ///< ZONE_UDP_QUERY: counter for UDP queries
- ZONE_TCP_QUERY, ///< ZONE_TCP_QUERY: counter for TCP queries
- PER_ZONE_COUNTER_TYPES ///< The number of defined counters
- };
/// The constructor.
///
/// This constructor is mostly exception free. But it may still throw
///
~Counters();
- /// \brief Increment the counter specified by the parameter.
- ///
- /// \param type Type of a counter to increment.
- ///
- /// \throw std::out_of_range \a type is unknown.
- ///
- /// usage: counter.inc(Counters::SERVER_UDP_QUERY);
- ///
- void inc(const ServerCounterType type);
-
- /// \brief Increment the counter of a per opcode counter.
- ///
- /// \note This is a tentative interface. See \c getCounter().
+ /// \brief Increment counters according to the parameters.
///
- /// \param opcode The opcode of the counter to increment.
+ /// \param qrattrs Query/Response attributes.
+ /// \param response DNS response message.
///
/// \throw None
- void inc(const isc::dns::Opcode opcode);
-
- /// \brief Increment the counter of a per rcode counter.
- ///
- /// \note This is a tentative interface. See \c getCounter().
///
- /// \param rcode The rcode of the counter to increment.
- ///
- /// \throw None
- void inc(const isc::dns::Rcode rcode);
+ void inc(const QRAttributes& qrattrs, const isc::dns::Message& response);
/// \brief Answers statistics counters to statistics module.
///
///
isc::data::ConstElementPtr getStatistics() const;
- /// \brief Get the value of a counter in the Counters.
- ///
- /// This function returns a value of the counter specified by \a type.
- /// This method never throws an exception.
- ///
- /// Note: Currently this function is for testing purpose only.
- ///
- /// \param type Type of a counter to get the value of
- ///
- /// \return the value of the counter specified by \a type.
- uint64_t getCounter(const Counters::ServerCounterType type) const;
-
- /// \brief Get the value of a per opcode counter.
- ///
- /// This method returns the value of the per opcode counter for the
- /// specified \c opcode.
- ///
- /// \note This is a tentative interface as an attempt of experimentally
- /// supporting more statistics counters. This should eventually be more
- /// generalized. In any case, this method is mainly for testing.
- ///
- /// \throw None
- /// \param opcode The opcode of the counter to get the value of
- /// \return the value of the counter.
- uint64_t getCounter(const isc::dns::Opcode opcode) const;
-
- /// \brief Get the value of a per rcode counter.
- ///
- /// This method returns the value of the per rcode counter for the
- /// specified \c rcode.
- ///
- /// \note As mentioned in getCounter(const isc::dns::Opcode opcode),
- /// This is a tentative interface as an attempt of experimentally
- /// supporting more statistics counters. This should eventually be more
- /// generalized. In any case, this method is mainly for testing.
- ///
- /// \throw None
- /// \param rcode The rcode of the counter to get the value of
- /// \return the value of the counter.
- uint64_t getCounter(const isc::dns::Rcode rcode) const;
-
/// \brief A type of validation function for the specification in
/// isc::config::ModuleSpec.
///
"rcode.other"
};
+const int QROpCodeToQRCounterType[16] = {
+ QR_OPCODE_QUERY,
+ QR_OPCODE_IQUERY,
+ QR_OPCODE_STATUS,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_NOTIFY,
+ QR_OPCODE_UPDATE,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_OTHER,
+ QR_OPCODE_OTHER
+};
+const int QRQTypeToQRCounterType[258] = {
+ QR_QTYPE_OTHER,
+ QR_QTYPE_A,
+ QR_QTYPE_NS,
+ QR_QTYPE_MD,
+ QR_QTYPE_MF,
+ QR_QTYPE_CNAME,
+ QR_QTYPE_SOA,
+ QR_QTYPE_MB,
+ QR_QTYPE_MG,
+ QR_QTYPE_MR,
+ QR_QTYPE_NULL,
+ QR_QTYPE_WKS,
+ QR_QTYPE_PTR,
+ QR_QTYPE_HINFO,
+ QR_QTYPE_MINFO,
+ QR_QTYPE_MX,
+ QR_QTYPE_TXT,
+ QR_QTYPE_RP,
+ QR_QTYPE_AFSDB,
+ QR_QTYPE_X25,
+ QR_QTYPE_ISDN,
+ QR_QTYPE_RT,
+ QR_QTYPE_NSAP,
+ QR_QTYPE_NSAP_PTR,
+ QR_QTYPE_SIG,
+ QR_QTYPE_KEY,
+ QR_QTYPE_PX,
+ QR_QTYPE_GPOS,
+ QR_QTYPE_AAAA,
+ QR_QTYPE_LOC,
+ QR_QTYPE_NXT,
+ QR_QTYPE_EID,
+ QR_QTYPE_NIMLOC,
+ QR_QTYPE_SRV,
+ QR_QTYPE_ATMA,
+ QR_QTYPE_NAPTR,
+ QR_QTYPE_KX,
+ QR_QTYPE_CERT,
+ QR_QTYPE_A6,
+ QR_QTYPE_DNAME,
+ QR_QTYPE_SINK,
+ QR_QTYPE_OPT,
+ QR_QTYPE_APL,
+ QR_QTYPE_DS,
+ QR_QTYPE_SSHFP,
+ QR_QTYPE_IPSECKEY,
+ QR_QTYPE_RRSIG,
+ QR_QTYPE_NSEC,
+ QR_QTYPE_DNSKEY,
+ QR_QTYPE_DHCID,
+ QR_QTYPE_NSEC3,
+ QR_QTYPE_NSEC3PARAM,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_HIP,
+ QR_QTYPE_NINFO,
+ QR_QTYPE_RKEY,
+ QR_QTYPE_TALINK,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_SPF,
+ QR_QTYPE_UINFO,
+ QR_QTYPE_UID,
+ QR_QTYPE_GID,
+ QR_QTYPE_UNSPEC,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_TKEY,
+ QR_QTYPE_TSIG,
+ QR_QTYPE_IXFR,
+ QR_QTYPE_AXFR,
+ QR_QTYPE_MAILB,
+ QR_QTYPE_MAILA,
+ QR_QTYPE_OTHER,
+ QR_QTYPE_URI,
+ QR_QTYPE_CAA
+};
+const int QRRCodeToQRCounterType[23] = {
+ QR_RCODE_NOERROR,
+ QR_RCODE_FORMERR,
+ QR_RCODE_SERVFAIL,
+ QR_RCODE_NXDOMAIN,
+ QR_RCODE_NOTIMP,
+ QR_RCODE_REFUSED,
+ QR_RCODE_YXDOMAIN,
+ QR_RCODE_YXRRSET,
+ QR_RCODE_NXRRSET,
+ QR_RCODE_NOTAUTH,
+ QR_RCODE_NOTZONE,
+ QR_RCODE_OTHER,
+ QR_RCODE_OTHER,
+ QR_RCODE_OTHER,
+ QR_RCODE_OTHER,
+ QR_RCODE_OTHER,
+ QR_RCODE_BADSIGVERS,
+ QR_RCODE_BADKEY,
+ QR_RCODE_BADTIME,
+ QR_RCODE_BADMODE,
+ QR_RCODE_BADNAME,
+ QR_RCODE_BADALG,
+ QR_RCODE_BADTRUNC
+};
+
} // anonymous namespace
#endif // __STATISTICS_ITEMS_H
#include <auth/command.h>
#include <auth/common.h>
#include <auth/statistics.h>
+#include <auth/statistics_items.h>
#include <auth/datasrc_configurator.h>
#include <util/unittests/mock_socketsession.h>
// Helper for checking Rcode statistic counters;
// Checks for one specific Rcode statistics counter value
- void checkRcodeCounter(const Rcode& rcode, int expected_value) const {
- EXPECT_EQ(expected_value, server.getCounter(rcode)) <<
- "Expected Rcode count for " << rcode.toText() <<
- " " << expected_value << ", was: " <<
- server.getCounter(rcode);
+ void checkRcodeCounter(const std::string& rcode_name, const int rcode_value,
+ const int expected_value) const
+ {
+ EXPECT_EQ(expected_value, rcode_value) <<
+ "Expected Rcode count for " << rcode_name <<
+ " " << expected_value << ", was: " <<
+ rcode_value;
}
// Checks whether all Rcode counters are set to zero
void checkAllRcodeCountersZero() const {
- for (int i = 0; i < 17; i++) {
- checkRcodeCounter(Rcode(i), 0);
+ const std::map<std::string, ConstElementPtr>
+ stats_map(server.getStatistics()->mapValue());
+
+ const std::string rcode_prefix("rcode.");
+ for (std::map<std::string, ConstElementPtr>::const_iterator
+ i = stats_map.begin(), e = stats_map.end();
+ i != e;
+ ++i)
+ {
+ if (i->first.compare(0, rcode_prefix.size(), rcode_prefix) == 0) {
+ checkRcodeCounter(i->first, i->second->intValue(), 0);
+ }
}
}
// Checks whether all Rcode counters are set to zero except the given
// rcode (it is checked to be set to 'value')
void checkAllRcodeCountersZeroExcept(const Rcode& rcode, int value) const {
- for (int i = 0; i < 17; i++) {
- const Rcode rc(i);
- if (rc == rcode) {
- checkRcodeCounter(Rcode(i), value);
- } else {
- checkRcodeCounter(Rcode(i), 0);
+ std::string target_rcode_name = rcode.toText();
+ std::transform(target_rcode_name.begin(), target_rcode_name.end(),
+ target_rcode_name.begin(), ::tolower);
+ // rcode 16 is registered as both BADVERS and BADSIG
+ if (target_rcode_name == "badvers") {
+ target_rcode_name = "badsigvers";
+ }
+
+ const std::map<std::string, ConstElementPtr>
+ stats_map(server.getStatistics()->mapValue());
+
+ const std::string rcode_prefix("rcode.");
+ for (std::map<std::string, ConstElementPtr>::const_iterator
+ i = stats_map.begin(), e = stats_map.end();
+ i != e;
+ ++i)
+ {
+ if (i->first.compare(0, rcode_prefix.size(), rcode_prefix) == 0) {
+ if (i->first.compare(rcode_prefix + target_rcode_name) == 0) {
+ checkRcodeCounter(i->first, i->second->intValue(), value);
+ } else {
+ checkRcodeCounter(i->first, i->second->intValue(), 0);
+ }
}
}
}
renderer.getLength());
}
+void
+expectCounterItem(ConstElementPtr stats,
+ const std::string& item, const int expected) {
+ ConstElementPtr value(Element::create(0));
+ if (item == "queries.udp" || item == "queries.tcp" || expected != 0) {
+ ASSERT_TRUE(stats->find(item, value)) << " Item: " << item;
+ value = stats->find(item);
+ EXPECT_EQ(expected, value->intValue()) << " Item: " << item;
+ } else {
+ ASSERT_FALSE(stats->find(item, value)) << " Item: " << item <<
+ std::endl << " Value: " << value->intValue();
+ }
+}
+
// We did not configure any client lists. Therefore it should be REFUSED
TEST_F(AuthSrvTest, noClientList) {
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
"It should be unsigned with this error";
// TSIG should have failed, and so the per opcode counter shouldn't be
// incremented.
- EXPECT_EQ(0, server.getCounter(Opcode::RESERVED14()));
+ ConstElementPtr stats = server.getStatistics();
+ expectCounterItem(stats, "opcode.normal", 0);
+ expectCounterItem(stats, "opcode.other", 0);
checkAllRcodeCountersZeroExcept(Rcode::NOTAUTH(), 1);
}
// Submit UDP normal query and check query counter
TEST_F(AuthSrvTest, queryCounterUDPNormal) {
- // The counter should be initialized to 0.
- EXPECT_EQ(0, server.getCounter(Counters::SERVER_UDP_QUERY));
+ // The counters should be initialized to 0.
+ ConstElementPtr stats_init = server.getStatistics();
+ expectCounterItem(stats_init, "queries.udp", 0);
+ expectCounterItem(stats_init, "queries.tcp", 0);
+ expectCounterItem(stats_init, "opcode.query", 0);
+ expectCounterItem(stats_init, "rcode.refused", 0);
// Create UDP message and process.
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
default_qid, Name("example.com"),
createRequestPacket(request_message, IPPROTO_UDP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
- // After processing UDP query, the counter should be 1.
- EXPECT_EQ(1, server.getCounter(Counters::SERVER_UDP_QUERY));
- // The counter for opcode Query should also be one
- EXPECT_EQ(1, server.getCounter(Opcode::QUERY()));
- // The counter for REFUSED responses should also be one, the rest zero
- checkAllRcodeCountersZeroExcept(Rcode::REFUSED(), 1);
+ // After processing the UDP query, these counters should be incremented:
+ // request.tcp, opcode.query, qtype.ns, rcode.refused, response
+ // and these counters should not be incremented:
+ // request.tcp
+ ConstElementPtr stats_after = server.getStatistics();
+ expectCounterItem(stats_after, "queries.udp", 1);
+ expectCounterItem(stats_after, "queries.tcp", 0);
+ expectCounterItem(stats_after, "opcode.query", 1);
+ expectCounterItem(stats_after, "rcode.refused", 1);
}
// Submit TCP normal query and check query counter
TEST_F(AuthSrvTest, queryCounterTCPNormal) {
- // The counter should be initialized to 0.
- EXPECT_EQ(0, server.getCounter(Counters::SERVER_TCP_QUERY));
+ // The counters should be initialized to 0.
+ ConstElementPtr stats_init = server.getStatistics();
+ expectCounterItem(stats_init, "queries.udp", 0);
+ expectCounterItem(stats_init, "queries.tcp", 0);
+ expectCounterItem(stats_init, "opcode.query", 0);
+ expectCounterItem(stats_init, "rcode.refused", 0);
// Create TCP message and process.
UnitTestUtil::createRequestMessage(request_message, Opcode::QUERY(),
default_qid, Name("example.com"),
createRequestPacket(request_message, IPPROTO_TCP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
- // After processing TCP query, the counter should be 1.
- EXPECT_EQ(1, server.getCounter(Counters::SERVER_TCP_QUERY));
- // The counter for SUCCESS responses should also be one
- EXPECT_EQ(1, server.getCounter(Opcode::QUERY()));
- // The counter for REFUSED responses should also be one, the rest zero
- checkAllRcodeCountersZeroExcept(Rcode::REFUSED(), 1);
+ // After processing the TCP query, these counters should be incremented:
+ // request.tcp, opcode.query, qtype.ns, rcode.refused, response
+ // and these counters should not be incremented:
+ // request.udp
+ ConstElementPtr stats_after = server.getStatistics();
+ expectCounterItem(stats_after, "queries.udp", 0);
+ expectCounterItem(stats_after, "queries.tcp", 1);
+ expectCounterItem(stats_after, "opcode.query", 1);
+ expectCounterItem(stats_after, "rcode.refused", 1);
}
// Submit TCP AXFR query and check query counter
TEST_F(AuthSrvTest, queryCounterTCPAXFR) {
- // The counter should be initialized to 0.
- EXPECT_EQ(0, server.getCounter(Counters::SERVER_TCP_QUERY));
+ // The counters should be initialized to 0.
+ ConstElementPtr stats_init = server.getStatistics();
+ expectCounterItem(stats_init, "queries.udp", 0);
+ expectCounterItem(stats_init, "queries.tcp", 0);
+ expectCounterItem(stats_init, "opcode.query", 0);
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("example.com"), RRClass::IN(), RRType::AXFR());
createRequestPacket(request_message, IPPROTO_TCP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
EXPECT_FALSE(dnsserv.hasAnswer());
- // After processing TCP AXFR query, the counter should be 1.
- EXPECT_EQ(1, server.getCounter(Counters::SERVER_TCP_QUERY));
- // No rcodes should be incremented
- checkAllRcodeCountersZero();
+ // After processing the TCP AXFR query, these counters should be
+ // incremented:
+ // request.tcp, opcode.query, qtype.axfr
+ // and these counters should not be incremented:
+ // request.udp, response
+ ConstElementPtr stats_after = server.getStatistics();
+ expectCounterItem(stats_after, "queries.udp", 0);
+ expectCounterItem(stats_after, "queries.tcp", 1);
+ expectCounterItem(stats_after, "opcode.query", 1);
}
// Submit TCP IXFR query and check query counter
TEST_F(AuthSrvTest, queryCounterTCPIXFR) {
- // The counter should be initialized to 0.
- EXPECT_EQ(0, server.getCounter(Counters::SERVER_TCP_QUERY));
+ // The counters should be initialized to 0.
+ ConstElementPtr stats_init = server.getStatistics();
+ expectCounterItem(stats_init, "queries.udp", 0);
+ expectCounterItem(stats_init, "queries.tcp", 0);
+ expectCounterItem(stats_init, "opcode.query", 0);
UnitTestUtil::createRequestMessage(request_message, opcode, default_qid,
Name("example.com"), RRClass::IN(), RRType::IXFR());
createRequestPacket(request_message, IPPROTO_TCP);
server.processMessage(*io_message, *parse_message, *response_obuffer,
&dnsserv);
EXPECT_FALSE(dnsserv.hasAnswer());
- // After processing TCP IXFR query, the counter should be 1.
- EXPECT_EQ(1, server.getCounter(Counters::SERVER_TCP_QUERY));
+ // After processing the TCP IXFR query, these counters should be
+ // incremented:
+ // request.tcp, opcode.query, qtype.ixfr
+ // and these counters should not be incremented:
+ // request.udp, response
+ ConstElementPtr stats_after = server.getStatistics();
+ expectCounterItem(stats_after, "queries.udp", 0);
+ expectCounterItem(stats_after, "queries.tcp", 1);
+ expectCounterItem(stats_after, "opcode.query", 1);
}
TEST_F(AuthSrvTest, queryCounterOpcodes) {
- for (int i = 0; i < 16; ++i) {
+ // Check for 0..2, 3(=other), 4..5
+ // The counter should be initialized to 0.
+ for (int i = 0; i < 6; ++i) {
// The counter should be initialized to 0.
- EXPECT_EQ(0, server.getCounter(Opcode(i)));
+ expectCounterItem(server.getStatistics(),
+ QRCounterItemName[QROpCodeToQRCounterType[i]], 0);
// For each possible opcode, create a request message and send it
UnitTestUtil::createRequestMessage(request_message, Opcode(i),
}
// Confirm the counter.
- EXPECT_EQ(i + 1, server.getCounter(Opcode(i)));
+ expectCounterItem(server.getStatistics(),
+ QRCounterItemName[QROpCodeToQRCounterType[i]],
+ i + 1);
+ }
+ // Check for 6..15
+ // they are treated as the 'other' opcode
+ // the 'other' opcode counter is 4 at this point
+ int expected = 4;
+ for (int i = 6; i < 16; ++i) {
+ // The counter should be initialized to 0.
+ expectCounterItem(server.getStatistics(),
+ QRCounterItemName[QROpCodeToQRCounterType[i]],
+ expected);
+
+ // For each possible opcode, create a request message and send it
+ UnitTestUtil::createRequestMessage(request_message, Opcode(i),
+ default_qid, Name("example.com"),
+ RRClass::IN(), RRType::NS());
+ createRequestPacket(request_message, IPPROTO_UDP);
+
+ // "send" the request once
+ parse_message->clear(Message::PARSE);
+ server.processMessage(*io_message, *parse_message,
+ *response_obuffer,
+ &dnsserv);
+
+ // the 'other' opcode counter should be incremented
+ ++expected;
+
+ // Confirm the counter.
+ expectCounterItem(server.getStatistics(),
+ QRCounterItemName[QROpCodeToQRCounterType[i]],
+ expected);
}
}
#include <dns/tests/unittest_util.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
using namespace std;
using namespace isc::cc;
using namespace isc::dns;
using namespace isc::data;
using isc::auth::statistics::Counters;
+using isc::auth::statistics::QRAttributes;
namespace {
class CountersTest : public ::testing::Test {
protected:
- CountersTest() : counters() {
- }
- ~CountersTest() {
- }
+ CountersTest() : counters() {}
+ ~CountersTest() {}
Counters counters;
- // no need to be inherited from the original class here.
- class MockModuleSpec {
- public:
- bool validateStatistics(ConstElementPtr, const bool valid) const
- { return (valid); }
- };
- MockModuleSpec module_spec_;
};
-TEST_F(CountersTest, incrementUDPCounter) {
- // The counter should be initialized to 0.
- EXPECT_EQ(0, counters.getCounter(Counters::SERVER_UDP_QUERY));
- EXPECT_NO_THROW(counters.inc(Counters::SERVER_UDP_QUERY));
- // After increment, the counter should be 1.
- EXPECT_EQ(1, counters.getCounter(Counters::SERVER_UDP_QUERY));
-}
-
-TEST_F(CountersTest, incrementTCPCounter) {
- // The counter should be initialized to 0.
- EXPECT_EQ(0, counters.getCounter(Counters::SERVER_TCP_QUERY));
- EXPECT_NO_THROW(counters.inc(Counters::SERVER_TCP_QUERY));
- // After increment, the counter should be 1.
- EXPECT_EQ(1, counters.getCounter(Counters::SERVER_TCP_QUERY));
-}
-
-TEST_F(CountersTest, incrementInvalidCounter) {
- // Expect to throw an isc::OutOfRange
- EXPECT_THROW(counters.inc(Counters::SERVER_COUNTER_TYPES),
- isc::OutOfRange);
-}
-
-TEST_F(CountersTest, incrementOpcodeCounter) {
- // The counter should be initialized to 0. If we increment it by 1
- // the counter should be 1.
- for (int i = 0; i < 16; ++i) {
- EXPECT_EQ(0, counters.getCounter(Opcode(i)));
- counters.inc(Opcode(i));
- EXPECT_EQ(1, counters.getCounter(Opcode(i)));
- }
-}
-
-TEST_F(CountersTest, incrementRcodeCounter) {
- // The counter should be initialized to 0. If we increment it by 1
- // the counter should be 1.
- for (int i = 0; i < 17; ++i) {
- EXPECT_EQ(0, counters.getCounter(Rcode(i)));
- counters.inc(Rcode(i));
- EXPECT_EQ(1, counters.getCounter(Rcode(i)));
- }
-}
-
-void
-opcodeDataCheck(ConstElementPtr data, const int expected[16]) {
- const char* item_names[] = {
- "query", "iquery", "status", "reserved3", "notify", "update",
- "reserved6", "reserved7", "reserved8", "reserved9", "reserved10",
- "reserved11", "reserved12", "reserved13", "reserved14", "reserved15",
- NULL
- };
- int i;
- for (i = 0; i < 16; ++i) {
- ASSERT_NE(static_cast<const char*>(NULL), item_names[i]);
- const string item_name = "opcode." + string(item_names[i]);
- if (expected[i] == 0) {
- EXPECT_FALSE(data->get(item_name));
- } else {
- EXPECT_EQ(expected[i], data->get(item_name)->intValue());
+bool
+checkCountersAllZeroExcept(const isc::data::ConstElementPtr counters,
+ const std::set<std::string>& except_for) {
+ std::map<std::string, ConstElementPtr> stats_map = counters->mapValue();
+
+ for (std::map<std::string, ConstElementPtr>::const_iterator
+ i = stats_map.begin(), e = stats_map.end();
+ i != e;
+ ++i)
+ {
+ int expect = 0;
+ if (except_for.count(i->first) != 0) {
+ expect = 1;
}
+ EXPECT_EQ(expect, i->second->intValue()) << "Expected counter "
+ << i->first << " = " << expect << ", actual: "
+ << i->second->intValue();
}
- // We should have examined all names
- ASSERT_EQ(static_cast<const char*>(NULL), item_names[i]);
-}
-void
-rcodeDataCheck(ConstElementPtr data, const int expected[17]) {
- const char* item_names[] = {
- "noerror", "formerr", "servfail", "nxdomain", "notimp", "refused",
- "yxdomain", "yxrrset", "nxrrset", "notauth", "notzone", "reserved11",
- "reserved12", "reserved13", "reserved14", "reserved15", "badvers",
- NULL
- };
- int i;
- for (i = 0; i < 17; ++i) {
- ASSERT_NE(static_cast<const char*>(NULL), item_names[i]);
- const string item_name = "rcode." + string(item_names[i]);
- if (expected[i] == 0) {
- EXPECT_FALSE(data->get(item_name));
- } else {
- EXPECT_EQ(expected[i], data->get(item_name)->intValue());
- }
- }
- // We should have examined all names
- ASSERT_EQ(static_cast<const char*>(NULL), item_names[i]);
+ return false;
}
-TEST_F(CountersTest, getStatisticsWithoutValidator) {
- // Get statistics data.
- // Validate if it answers correct data.
+TEST_F(CountersTest, incrementNormalQuery) {
+ Message response(Message::RENDER);
+ QRAttributes qrattrs;
+ std::set<std::string> expect_nonzero;
- // Counters should be initialized to 0.
- EXPECT_EQ(0, counters.getCounter(Counters::SERVER_UDP_QUERY));
- EXPECT_EQ(0, counters.getCounter(Counters::SERVER_TCP_QUERY));
+ expect_nonzero.clear();
+ checkCountersAllZeroExcept(counters.getStatistics(), expect_nonzero);
- // UDP query counter is set to 2.
- counters.inc(Counters::SERVER_UDP_QUERY);
- counters.inc(Counters::SERVER_UDP_QUERY);
- // TCP query counter is set to 1.
- counters.inc(Counters::SERVER_TCP_QUERY);
- ConstElementPtr statistics_data = counters.getStatistics();
+ qrattrs.setQueryIPVersion(AF_INET6);
+ qrattrs.setQueryTransportProtocol(IPPROTO_UDP);
+ qrattrs.setQueryOpCode(Opcode::QUERY_CODE);
+ qrattrs.setQueryEDNS(true, false);
+ qrattrs.setQueryDO(true);
+ qrattrs.answerWasSent();
- // UDP query counter is 2 and TCP query counter is 1.
- EXPECT_EQ(2, statistics_data->get("queries.udp")->intValue());
- EXPECT_EQ(1, statistics_data->get("queries.tcp")->intValue());
+ response.setRcode(Rcode::REFUSED());
+ response.addQuestion(Question(Name("example.com"),
+ RRClass::IN(), RRType::AAAA()));
- // By default opcode counters are all 0 and omitted
- const int opcode_results[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0 };
- opcodeDataCheck(statistics_data, opcode_results);
- // By default rcode counters are all 0 and omitted
- const int rcode_results[17] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0 };
- rcodeDataCheck(statistics_data, rcode_results);
-}
+ counters.inc(qrattrs, response);
-void
-updateOpcodeCounters(Counters &counters, const int expected[16]) {
- for (int i = 0; i < 16; ++i) {
- for (int j = 0; j < expected[i]; ++j) {
- counters.inc(Opcode(i));
- }
- }
+ expect_nonzero.clear();
+ expect_nonzero.insert("opcode.query");
+ expect_nonzero.insert("queries.udp");
+ expect_nonzero.insert("rcode.refused");
+ checkCountersAllZeroExcept(counters.getStatistics(), expect_nonzero);
}
-void
-updateRcodeCounters(Counters &counters, const int expected[17]) {
- for (int i = 0; i < 17; ++i) {
- for (int j = 0; j < expected[i]; ++j) {
- counters.inc(Rcode(i));
- }
+TEST_F(CountersTest, getStatistics) {
+ std::map<std::string, ConstElementPtr> stats_map =
+ counters.getStatistics()->mapValue();
+ for (std::map<std::string, ConstElementPtr>::const_iterator
+ i = stats_map.begin(), e = stats_map.end();
+ i != e;
+ ++i)
+ {
+ // item type check
+ EXPECT_NO_THROW(i->second->intValue())
+ << "Item " << i->first << " is not IntElement";
}
}
-TEST_F(CountersTest, getStatisticsWithOpcodeCounters) {
- // Increment some of the opcode counters. Then they should appear in the
- // submitted data; others shouldn't
- const int opcode_results[16] = { 1, 2, 3, 0, 4, 5, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0 };
- updateOpcodeCounters(counters, opcode_results);
- ConstElementPtr statistics_data = counters.getStatistics();
- opcodeDataCheck(statistics_data, opcode_results);
-}
-
-TEST_F(CountersTest, getStatisticsWithAllOpcodeCounters) {
- // Increment all opcode counters. Then they should appear in the
- // submitted data.
- const int opcode_results[16] = { 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1 };
- updateOpcodeCounters(counters, opcode_results);
- ConstElementPtr statistics_data = counters.getStatistics();
- opcodeDataCheck(statistics_data, opcode_results);
-}
-
-TEST_F(CountersTest, getStatisticsWithRcodeCounters) {
- // Increment some of the rcode counters. Then they should appear in the
- // submitted data; others shouldn't
- const int rcode_results[17] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
- 10, 0, 0, 0, 0, 0, 0, 11 };
- updateRcodeCounters(counters, rcode_results);
- ConstElementPtr statistics_data = counters.getStatistics();
- rcodeDataCheck(statistics_data, rcode_results);
-}
-
-TEST_F(CountersTest, getStatisticsWithAllRcodeCounters) {
- // Increment all rcode counters. Then they should appear in the
- // submitted data.
- const int rcode_results[17] = { 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1 };
- updateOpcodeCounters(counters, rcode_results);
- ConstElementPtr statistics_data = counters.getStatistics();
- opcodeDataCheck(statistics_data, rcode_results);
-}
-
-TEST_F(CountersTest, getStatisticsWithValidator) {
-
- //a validator for the unittest
- Counters::validator_type validator;
- ConstElementPtr el;
-
- // Get statistics data with correct statistics validator.
- validator = boost::bind(
- &CountersTest::MockModuleSpec::validateStatistics,
- &module_spec_, _1, true);
-
- EXPECT_TRUE(validator(el));
-
- // register validator to Counters
- counters.registerStatisticsValidator(validator);
-
- // Counters should be initialized to 0.
- EXPECT_EQ(0, counters.getCounter(Counters::SERVER_UDP_QUERY));
- EXPECT_EQ(0, counters.getCounter(Counters::SERVER_TCP_QUERY));
-
- // UDP query counter is set to 2.
- counters.inc(Counters::SERVER_UDP_QUERY);
- counters.inc(Counters::SERVER_UDP_QUERY);
- // TCP query counter is set to 1.
- counters.inc(Counters::SERVER_TCP_QUERY);
-
- // checks the value returned by getStatistics
- ConstElementPtr statistics_data = counters.getStatistics();
-
- // UDP query counter is 2 and TCP query counter is 1.
- EXPECT_EQ(2, statistics_data->get("queries.udp")->intValue());
- EXPECT_EQ(1, statistics_data->get("queries.tcp")->intValue());
-
- // Get statistics data with incorrect statistics validator.
- validator = boost::bind(
- &CountersTest::MockModuleSpec::validateStatistics,
- &module_spec_, _1, false);
-
- EXPECT_FALSE(validator(el));
-
- counters.registerStatisticsValidator(validator);
-
- // checks the value returned by getStatistics
- EXPECT_FALSE(counters.getStatistics());
-}
-
TEST(StatisticsItemsTest, QRItemNamesCheck) {
// check the number of elements in the array
EXPECT_EQ(sizeof(QRCounterItemName) / sizeof(QRCounterItemName[0]),