Commit 72941a64 authored by Yoshitaka Aharen's avatar Yoshitaka Aharen
Browse files

[2155] modify Counters::inc() to update new counters

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.
parent 3c3bea55
......@@ -145,7 +145,7 @@
"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"
},
{
......@@ -180,14 +180,6 @@
"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",
......@@ -205,84 +197,12 @@
"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",
......@@ -373,52 +293,68 @@
"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)"
}
]
}
......
......@@ -296,27 +296,29 @@ public:
/// \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;
......@@ -500,6 +502,12 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
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.
......@@ -509,13 +517,13 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& 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;
}
......@@ -526,13 +534,13 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
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.
......@@ -555,21 +563,35 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
**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,
......@@ -611,7 +633,7 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
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
......@@ -628,9 +650,6 @@ AuthSrvImpl::processNormalQuery(const IOMessage& io_message, Message& message,
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);
......@@ -675,9 +694,6 @@ AuthSrvImpl::processXfrQuery(const IOMessage& io_message, Message& message,
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(),
......@@ -809,19 +825,6 @@ AuthSrvImpl::processUpdate(const IOMessage& io_message) {
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(
......@@ -839,10 +842,15 @@ AuthSrvImpl::validateStatistics(isc::data::ConstElementPtr data) const {
}
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);
}
......@@ -865,21 +873,6 @@ ConstElementPtr AuthSrv::getStatistics() const {
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_);
......
......@@ -210,52 +210,6 @@ public:
/// \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.
*/
......
......@@ -13,9 +13,11 @@
// 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>
......@@ -32,6 +34,12 @@
#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;
......@@ -47,90 +55,189 @@ class CountersImpl : boost::noncopyable {
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);