"item_default": 0,
"item_title": "Queries UDP",
"item_description": "A number of total query counts which all auth servers receive over UDP since they started initially"
+ },
+ {
+ "item_name": "opcode.query",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received query requests",
+ "item_description": "The number of total request counts whose opcode is query"
+ },
+ {
+ "item_name": "opcode.iquery",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received inverse query requests",
+ "item_description": "The number of total request counts whose opcode is inverse query"
+ },
+ {
+ "item_name": "opcode.status",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "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_optional": true,
+ "item_default": 0,
+ "item_title": "Received notify requests",
+ "item_description": "The number of total request counts whose opcode is notify"
+ },
+ {
+ "item_name": "opcode.update",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received update requests",
+ "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 opcode8",
+ "item_description": "The number of total request counts whose opcode is8 (reserved)"
+ },
+ {
+ "item_name": "opcode.reserved9",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received requests opcode9",
+ "item_description": "The number of total request counts whose opcode is9 (reserved)"
+ },
+ {
+ "item_name": "opcode.reserved10",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received requests opcode10",
+ "item_description": "The number of total request counts whose opcode is10 (reserved)"
+ },
+ {
+ "item_name": "opcode.reserved11",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received requests opcode11",
+ "item_description": "The number of total request counts whose opcode is11 (reserved)"
+ },
+ {
+ "item_name": "opcode.reserved12",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received requests opcode12",
+ "item_description": "The number of total request counts whose opcode is12 (reserved)"
+ },
+ {
+ "item_name": "opcode.reserved13",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received requests opcode13",
+ "item_description": "The number of total request counts whose opcode is13 (reserved)"
+ },
+ {
+ "item_name": "opcode.reserved14",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received requests opcode14",
+ "item_description": "The number of total request counts whose opcode is14 (reserved)"
+ },
+ {
+ "item_name": "opcode.reserved15",
+ "item_type": "integer",
+ "item_optional": true,
+ "item_default": 0,
+ "item_title": "Received requests opcode15",
+ "item_description": "The number of total request counts whose opcode is15 (reserved)"
}
]
}
io_message.getDataSize());
}
- bool sendAnswer = true;
if (tsig_error != TSIGError::NOERROR()) {
makeErrorMessage(message, buffer, tsig_error.toRcode(), tsig_context);
- } else if (message->getOpcode() == Opcode::NOTIFY()) {
- sendAnswer = impl_->processNotify(io_message, message, buffer,
- tsig_context);
+ server->resume(true);
+ return;
+ }
+
+ // update per opcode statistics counter. This can only be reliable after
+ // TSIG check succeeds.
+ impl_->counters_.inc(message->getOpcode());
+
+ bool send_answer = true;
+ if (message->getOpcode() == Opcode::NOTIFY()) {
+ send_answer = impl_->processNotify(io_message, message, buffer,
+ tsig_context);
} else if (message->getOpcode() != Opcode::QUERY()) {
LOG_DEBUG(auth_logger, DBG_AUTH_DETAIL, AUTH_UNSUPPORTED_OPCODE)
.arg(message->getOpcode().toText());
ConstQuestionPtr question = *message->beginQuestion();
const RRType &qtype = question->getType();
if (qtype == RRType::AXFR()) {
- sendAnswer = impl_->processXfrQuery(io_message, message, buffer,
- tsig_context);
+ send_answer = impl_->processXfrQuery(io_message, message, buffer,
+ tsig_context);
} else if (qtype == RRType::IXFR()) {
- sendAnswer = impl_->processXfrQuery(io_message, message, buffer,
- tsig_context);
+ send_answer = impl_->processXfrQuery(io_message, message, buffer,
+ tsig_context);
} else {
- sendAnswer = impl_->processNormalQuery(io_message, message, buffer,
- tsig_context);
+ send_answer = impl_->processNormalQuery(io_message, message,
+ buffer, tsig_context);
}
}
- server->resume(sendAnswer);
+ server->resume(send_answer);
}
bool
return (impl_->counters_.getCounter(type));
}
+uint64_t
+AuthSrv::getCounter(const Opcode opcode) const {
+ return (impl_->counters_.getCounter(opcode));
+}
+
const AddressList&
AuthSrv::getListenAddresses() const {
return (impl_->listen_addresses_);
#include <cc/data.h>
#include <config/ccsession.h>
#include <dns/message.h>
+#include <dns/opcode.h>
#include <util/buffer.h>
#include <asiodns/dns_server.h>
/// \return the value of the counter.
uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
+ /// \brief Get the value of per Opcode counter in the Auth Counters.
+ ///
+ /// This function calls AuthCounters::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 Set and get the addresses we listen on.
*/
#include <auth/statistics.h>
#include <auth/auth_log.h>
+#include <dns/opcode.h>
+
#include <cc/data.h>
#include <cc/session.h>
#include <statistics/counter.h>
#include <statistics/counter_dict.h>
+#include <algorithm>
+#include <cctype>
+#include <cassert>
+#include <string>
#include <sstream>
#include <iostream>
#include <boost/noncopyable.hpp>
+using namespace isc::dns;
using namespace isc::auth;
using namespace isc::statistics;
AuthCountersImpl();
~AuthCountersImpl();
void inc(const AuthCounters::ServerCounterType type);
+ void inc(const Opcode opcode) {
+ opcode_counter_.inc(opcode.getCode());
+ }
void inc(const std::string& zone,
const AuthCounters::PerZoneCounterType type);
bool submitStatistics() const;
(AuthCounters::validator_type validator);
// Currently for testing purpose only
uint64_t getCounter(const AuthCounters::ServerCounterType type) const;
+ uint64_t getCounter(const Opcode opcode) const {
+ return (opcode_counter_.get(opcode.getCode()));
+ }
private:
Counter server_counter_;
+ Counter opcode_counter_;
+ static const size_t NUM_OPCODES = 16;
CounterDictionary per_zone_counter_;
isc::cc::AbstractSession* statistics_session_;
AuthCounters::validator_type validator_;
// size of server_counter_: AuthCounters::SERVER_COUNTER_TYPES
// size of per_zone_counter_: AuthCounters::PER_ZONE_COUNTER_TYPES
server_counter_(AuthCounters::SERVER_COUNTER_TYPES),
+ opcode_counter_(NUM_OPCODES),
per_zone_counter_(AuthCounters::PER_ZONE_COUNTER_TYPES),
statistics_session_(NULL)
{
<< "{ \"queries.udp\": "
<< server_counter_.get(AuthCounters::SERVER_UDP_QUERY)
<< ", \"queries.tcp\": "
- << server_counter_.get(AuthCounters::SERVER_TCP_QUERY)
- << " }"
+ << server_counter_.get(
+ AuthCounters::SERVER_TCP_QUERY);
+ // Insert non 0 Opcode counters.
+ for (int i = 0; i < NUM_OPCODES; ++i) {
+ const Counter::Type counter = opcode_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 << "\": "
+ << counter;
+ }
+ }
+ statistics_string << " }"
<< "}"
<< "]}";
isc::data::ConstElementPtr statistics_element =
impl_->inc(type);
}
+void
+AuthCounters::inc(const Opcode opcode) {
+ impl_->inc(opcode);
+}
+
bool
AuthCounters::submitStatistics() const {
return (impl_->submitStatistics());
return (impl_->getCounter(type));
}
+uint64_t
+AuthCounters::getCounter(const Opcode opcode) const {
+ return (impl_->getCounter(opcode));
+}
+
void
AuthCounters::registerStatisticsValidator
(AuthCounters::validator_type validator) const
#ifndef __STATISTICS_H
#define __STATISTICS_H 1
+#include <dns/opcode.h>
+
#include <cc/session.h>
#include <stdint.h>
#include <boost/scoped_ptr.hpp>
///
void inc(const ServerCounterType type);
+ /// \brief Increment the counter of a per opcode counter.
+ ///
+ /// \note This is a tentative interface. See \c getCounter().
+ ///
+ /// \param opcode The opcode of the counter to increment.
+ ///
+ /// \throw None
+ void inc(const isc::dns::Opcode opcode);
+
/// \brief Submit statistics counters to statistics module.
///
/// This method is desinged to be called periodically
///
void setStatisticsSession(isc::cc::AbstractSession* statistics_session);
- /// \brief Get a value of a counter in the AuthCounters.
+ /// \brief Get the value of a counter in the AuthCounters.
///
/// This function returns a value of the counter specified by \a type.
/// This method never throws an exception.
/// \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 AuthCounters::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 A type of validation function for the specification in
/// isc::config::ModuleSpec.
///
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <dns/name.h>
+#include <dns/opcode.h>
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <dns/rrttl.h>
EXPECT_EQ(TSIGError::BAD_SIG_CODE, tsig->getRdata().getError());
EXPECT_EQ(0, tsig->getRdata().getMACSize()) <<
"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()));
}
TEST_F(AuthSrvTest, AXFRConnectFail) {
EXPECT_EQ(1, server.getCounter(AuthCounters::SERVER_TCP_QUERY));
}
+TEST_F(AuthSrvTest, queryCounterOpcodes) {
+ for (int i = 0; i < 16; ++i) {
+ // The counter should be initialized to 0.
+ EXPECT_EQ(0, server.getCounter(Opcode(i)));
+
+ // 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 N-th times where N is i + 1 for i-th code.
+ // we intentionally use different values for each code
+ for (int j = 0; j <= i; ++j) {
+ parse_message->clear(Message::PARSE);
+ server.processMessage(*io_message, parse_message, response_obuffer,
+ &dnsserv);
+ }
+
+ // Confirm the counter.
+ EXPECT_EQ(i + 1, server.getCounter(Opcode(i)));
+ }
+}
+
// class for queryCounterUnexpected test
// getProtocol() returns IPPROTO_IP
class DummyUnknownSocket : public IOSocket {
#include <config.h>
+#include <string>
+
#include <gtest/gtest.h>
#include <boost/bind.hpp>
+#include <dns/opcode.h>
+
#include <cc/data.h>
#include <cc/session.h>
isc::OutOfRange);
}
+TEST_F(AuthCountersTest, 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(AuthCountersTest, submitStatisticsWithoutSession) {
// Set statistics_session to NULL and call submitStatistics().
// Expect to return false.
statistics_session_.setThrowSessionTimeout(false);
}
+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());
+ }
+ }
+ // We should have examined all names
+ ASSERT_EQ(static_cast<const char*>(NULL), item_names[i]);
+}
+
TEST_F(AuthCountersTest, submitStatisticsWithoutValidator) {
// Submit statistics data.
// Validate if it submits correct data.
// 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());
+
+ // 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);
+}
+
+void
+updateOpcodeCounters(AuthCounters &counters, const int expected[16]) {
+ for (int i = 0; i < 16; ++i) {
+ for (int j = 0; j < expected[i]; ++j) {
+ counters.inc(Opcode(i));
+ }
+ }
+}
+
+TEST_F(AuthCountersTest, submitStatisticsWithOpcodeCounters) {
+ // 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);
+ counters.submitStatistics();
+ ConstElementPtr statistics_data = statistics_session_.sent_msg
+ ->get("command")->get(1)->get("data");
+ opcodeDataCheck(statistics_data, opcode_results);
+}
+
+TEST_F(AuthCountersTest, submitStatisticsWithAllOpcodeCounters) {
+ // 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);
+ counters.submitStatistics();
+ ConstElementPtr statistics_data = statistics_session_.sent_msg
+ ->get("command")->get(1)->get("data");
+ opcodeDataCheck(statistics_data, opcode_results);
}
TEST_F(AuthCountersTest, submitStatisticsWithValidator) {