Commit 23492e5e authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[2097] Merge branch 'trac2096' into trac2097 with fixing conflicts.

It's mainly about renaming the header file.  Also, define empty
action callbacks within RdataReader again as I noticed it would be
useful for RdataSet implementation (and for some other purposes,
such as additional section processing).
parents 9c03bc82 50ab96b1
......@@ -1165,6 +1165,7 @@ AC_CONFIG_FILES([Makefile
src/lib/datasrc/Makefile
src/lib/datasrc/memory/Makefile
src/lib/datasrc/memory/tests/Makefile
src/lib/datasrc/memory/benchmarks/Makefile
src/lib/datasrc/tests/Makefile
src/lib/datasrc/tests/testdata/Makefile
src/lib/xfr/Makefile
......
SUBDIRS = . tests
SUBDIRS = . tests benchmarks
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
......@@ -11,8 +11,7 @@ CLEANFILES = *.gcno *.gcda datasrc_messages.h datasrc_messages.cc
noinst_LTLIBRARIES = libdatasrc_memory.la
libdatasrc_memory_la_SOURCES = \
rdata_encoder.h rdata_encoder.cc \
rdata_field.h rdata_field.cc \
rdata_reader.h rdata_reader.cc \
rdataset.h rdataset.cc \
rdata_serialization.h rdata_serialization.cc \
domaintree.h
EXTRA_DIST = rdata_serialization_priv.cc
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES)
AM_CXXFLAGS = $(B10_CXXFLAGS)
if USE_STATIC_LINK
AM_LDFLAGS = -static
endif
CLEANFILES = *.gcno *.gcda
noinst_PROGRAMS = rdata_reader_bench
rdata_reader_bench_SOURCES = rdata_reader_bench.cc
rdata_reader_bench_LDADD = $(top_builddir)/src/lib/datasrc/memory/libdatasrc_memory.la
rdata_reader_bench_LDADD += $(top_builddir)/src/lib/dns/libb10-dns++.la
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <bench/benchmark.h>
#include <util/buffer.h>
#include <dns/name.h>
#include <dns/messagerenderer.h>
#include <dns/rrset.h>
#include <dns/rrclass.h>
#include <dns/masterload.h>
#include <datasrc/memory/rdata_serialization.h>
#include <boost/bind.hpp>
#include <vector>
#include <sstream>
#include <unistd.h>
using std::vector;
using namespace isc::bench;
using namespace isc::datasrc::memory;
using namespace isc::dns;
namespace {
struct EncodeParam {
EncodeParam(RdataEncoder& encoder, ConstRRsetPtr rrset,
ConstRRsetPtr sig_rrset = ConstRRsetPtr()) :
rrclass(rrset->getClass()), rrtype(rrset->getType()),
rdata_count(rrset->getRdataCount()),
sig_count(sig_rrset ? sig_rrset->getRdataCount() : 0)
{
encoder.start(rrclass, rrtype);
for (RdataIteratorPtr it = rrset->getRdataIterator();
!it->isLast();
it->next()) {
encoder.addRdata(it->getCurrent());
}
if (sig_rrset) {
for (RdataIteratorPtr it = sig_rrset->getRdataIterator();
!it->isLast();
it->next())
{
encoder.addSIGRdata(it->getCurrent());
}
}
const size_t data_len = encoder.getStorageLength();
data.resize(data_len);
encoder.encode(&data[0], data.size());
}
RRClass rrclass;
RRType rrtype;
size_t rdata_count;
size_t sig_count;
vector<uint8_t> data;
};
// Encapsulating parameters for a RdataReader. It extracts from the given
// RRset and its RRSIGs parameters that are necessary construct an RdataReader.
// RDATA data will be stored in the 'data' vector.
// members are defined as non const so we can use the object of this struct
// in a vector.
class ReaderBenchMark {
public:
ReaderBenchMark(const vector<EncodeParam>& encode_params,
MessageRenderer& renderer) :
encode_params_(encode_params), renderer_(renderer)
{}
unsigned int run() {
vector<EncodeParam>::const_iterator it;
const vector<EncodeParam>::const_iterator it_end =
encode_params_.end();
renderer_.clear();
for (it = encode_params_.begin(); it != it_end; ++it) {
RdataReader reader(it->rrclass, it->rrtype, &it->data[0],
it->rdata_count, it->sig_count,
boost::bind(&ReaderBenchMark::renderName,
this, _1, _2),
boost::bind(&ReaderBenchMark::renderData,
this, _1, _2));
reader.iterate();
reader.iterateAllSigs();
}
return (1);
}
void renderName(const LabelSequence& labels,
RdataNameAttributes attributes)
{
const bool compress =
(attributes & NAMEATTR_COMPRESSIBLE) != 0;
renderer_.writeName(labels, compress);
}
void renderData(const void* data, size_t data_len) {
renderer_.writeData(data, data_len);
}
private:
const vector<EncodeParam>& encode_params_;
MessageRenderer& renderer_;
};
// Builtin benchmark data. This is a list of RDATA (of RRs) in a response
// from a root server for the query for "www.example.com" (as of this
// implementation). We use a real world example to make the case practical.
const char* const rrsets_txt =
// AUTHORITY SECTION (NS)
"com. 172800 IN NS a.gtld-servers.net.\n"
"com. 172800 IN NS b.gtld-servers.net.\n"
"com. 172800 IN NS c.gtld-servers.net.\n"
"com. 172800 IN NS d.gtld-servers.net.\n"
"com. 172800 IN NS e.gtld-servers.net.\n"
"com. 172800 IN NS f.gtld-servers.net.\n"
"com. 172800 IN NS g.gtld-servers.net.\n"
"com. 172800 IN NS h.gtld-servers.net.\n"
"com. 172800 IN NS i.gtld-servers.net.\n"
"com. 172800 IN NS j.gtld-servers.net.\n"
"com. 172800 IN NS k.gtld-servers.net.\n"
"com. 172800 IN NS l.gtld-servers.net.\n"
"com. 172800 IN NS m.gtld-servers.net.\n"
// AUTHORITY SECTION (DS)
"com. 86400 IN DS 30909 8 2 "
"E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CFC41A5766\n"
// AUTHORITY SECTION (RRSIG for DS)
"com. 86400 IN RRSIG DS 8 1 86400 20120822000000 20120814230000 50398 . "
"lcIpLRq4s91Fh1FihDXiDvVMMRqgy2jjlpiP4Y6sSjIrLue6Boi7xraj"
"Ouka34ubpl4KuIcopWe99LI/7Npvq0MYr9DaqfnX9dTW6Vc2C7/hKSsz"
"POYjraZZA3SCApgfNVzq+AscYlShi56f1vm7DQWw1eh1wHLdatidrQwNyDo=\n"
// ADDITIONAL SECTION
"a.gtld-servers.net. 172800 IN A 192.5.6.30\n"
"b.gtld-servers.net. 172800 IN A 192.33.14.30\n"
"c.gtld-servers.net. 172800 IN A 192.26.92.30\n"
"d.gtld-servers.net. 172800 IN A 192.31.80.30\n"
"e.gtld-servers.net. 172800 IN A 192.12.94.30\n"
"f.gtld-servers.net. 172800 IN A 192.35.51.30\n"
"g.gtld-servers.net. 172800 IN A 192.42.93.30\n"
"h.gtld-servers.net. 172800 IN A 192.54.112.30\n"
"i.gtld-servers.net. 172800 IN A 192.43.172.30\n"
"j.gtld-servers.net. 172800 IN A 192.48.79.30\n"
"k.gtld-servers.net. 172800 IN A 192.52.178.30\n"
"l.gtld-servers.net. 172800 IN A 192.41.162.30\n"
"m.gtld-servers.net. 172800 IN A 192.55.83.30\n"
"a.gtld-servers.net. 172800 IN AAAA 2001:503:a83e::2:30\n"
"b.gtld-servers.net. 172800 IN AAAA 2001:503:231d::2:30";
void
usage() {
std::cerr << "Usage: rdata_reader_bench [-n iterations]" << std::endl;
exit (1);
}
// Helper callback for masterLoad() used in main() to build test data.
void
setRRset(vector<ConstRRsetPtr>* rrsets, ConstRRsetPtr rrset) {
rrsets->push_back(rrset);
}
}
int
main(int argc, char* argv[]) {
int ch;
int iteration = 100000;
while ((ch = getopt(argc, argv, "n:")) != -1) {
switch (ch) {
case 'n':
iteration = atoi(optarg);
break;
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 0) {
usage();
}
// Build test data. rrsets will consist of a list of RRsets corresponding
// to rrsets_txt defined above.
vector<ConstRRsetPtr> rrsets;
std::stringstream rrsets_stream(rrsets_txt);
masterLoad(rrsets_stream, Name::ROOT_NAME(), RRClass::IN(),
boost::bind(setRRset, &rrsets, _1));
// Create EncodeParam for each RRset (possibly with RRSIG) in rrsets,
// and store them in encode_param_list. It's the direct test input.
vector<EncodeParam> encode_param_list;
RdataEncoder encoder;
encode_param_list.push_back(EncodeParam(encoder, rrsets.at(0)));
encode_param_list.push_back(EncodeParam(encoder, rrsets.at(1),
rrsets.at(2)));
for (vector<ConstRRsetPtr>::const_iterator it = rrsets.begin() + 3;
it != rrsets.end();
++it) {
encode_param_list.push_back(EncodeParam(encoder, *it));
}
// The benchmark test uses a message renderer. Create it now and keep
// using it throughout the test.
isc::util::OutputBuffer buffer(4096); // 4096 should be sufficiently large
MessageRenderer renderer;
renderer.setBuffer(&buffer);
std::cout << "Benchmark for RdataReader" << std::endl;
BenchMark<ReaderBenchMark>(iteration,
ReaderBenchMark(encode_param_list, renderer));
return (0);
}
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "rdata_field.h"
#include <dns/rrclass.h>
#include <dns/rrtype.h>
#include <boost/static_assert.hpp>
using namespace isc::dns;
namespace isc {
namespace datasrc {
namespace memory {
namespace {
// Many types of RDATA can be treated as a single-field, variable length
// field (in terms of our encoding). The following define such most general
// form of field spec.
const RdataFieldSpec generic_data_fields[] = {
{RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE}
};
const uint16_t n_generic_data_fields =
sizeof(generic_data_fields) / sizeof(RdataFieldSpec);
const RdataEncodeSpec generic_data_spec = {
n_generic_data_fields, 0, 1, generic_data_fields
};
// RDATA consist of a single IPv4 address field.
const RdataFieldSpec single_ipv4_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint32_t), NAMEATTR_NONE}
};
const uint16_t n_ipv4_fields =
sizeof(single_ipv4_fields) / sizeof(RdataFieldSpec);
// RDATA consist of a single IPv6 address field.
const RdataFieldSpec single_ipv6_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, 16, NAMEATTR_NONE} // 128bits = 16 bytes
};
const uint16_t n_ipv6_fields =
sizeof(single_ipv6_fields) / sizeof(RdataFieldSpec);
// There are several RR types that consist of a single domain name.
const RdataFieldSpec single_noattr_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
};
const RdataFieldSpec single_compressible_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE}
};
const RdataFieldSpec single_compadditional_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0,
static_cast<RdataNameAttributes>(
static_cast<unsigned int>(NAMEATTR_COMPRESSIBLE) |
static_cast<unsigned int>(NAMEATTR_ADDITIONAL))}
};
const uint16_t n_single_name_fields =
sizeof(single_noattr_name_fields) / sizeof(RdataFieldSpec);
// RDATA consisting of two names. There are some of this type.
const RdataFieldSpec double_compressible_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE}
};
const RdataFieldSpec double_noattr_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
};
const uint16_t n_double_name_fields =
sizeof(double_compressible_name_fields) / sizeof(RdataFieldSpec);
// SOA specific: two compressible names + 5*32-bit data
const RdataFieldSpec soa_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint32_t) * 5, NAMEATTR_NONE}
};
const uint16_t n_soa_fields = sizeof(soa_fields) / sizeof(RdataFieldSpec);
// MX specific: 16-bit data + compressible/additional name
const RdataFieldSpec mx_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t), NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0,
static_cast<RdataNameAttributes>(
static_cast<unsigned int>(NAMEATTR_COMPRESSIBLE) |
static_cast<unsigned int>(NAMEATTR_ADDITIONAL))}
};
const uint16_t n_mx_fields = sizeof(mx_fields) / sizeof(RdataFieldSpec);
// AFSDB specific: 16-bit data + no-attribute name
const RdataFieldSpec afsdb_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t), NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
};
const uint16_t n_afsdb_fields = sizeof(afsdb_fields) / sizeof(RdataFieldSpec);
// SRV specific: 3*16-bit data + additional name
const RdataFieldSpec srv_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t) * 3, NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_ADDITIONAL}
};
const uint16_t n_srv_fields = sizeof(srv_fields) / sizeof(RdataFieldSpec);
// NAPTR specific: (multi-field) variable data + (additional) name
// NAPTR requires complicated additional section handling; for now, we skip
// the additional handling completely.
const RdataFieldSpec naptr_fields[] = {
{RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
};
const uint16_t n_naptr_fields = sizeof(naptr_fields) / sizeof(RdataFieldSpec);
// NSEC specific: no-attribute name + varlen data
const RdataFieldSpec nsec_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE},
{RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE}
};
const uint16_t n_nsec_fields = sizeof(nsec_fields) / sizeof(RdataFieldSpec);
// Class IN encode specs. This gives a shortcut to the encode spec for
// some well-known types of RDATA specific to class IN (most of which are
// generic and can be used for other classes). The array index is the
// RR type code.
const RdataEncodeSpec encode_spec_list_in[] = {
generic_data_spec, // #0: (NONE)
{n_ipv4_fields, 0, 0, single_ipv4_fields}, // #1: A
{n_single_name_fields, 1, 0, single_compadditional_name_fields}, // #2: NS
generic_data_spec, // #3
generic_data_spec, // #4
{n_single_name_fields, 1, 0, single_compressible_name_fields}, // #5: CNAME
{n_soa_fields, 2, 0, soa_fields}, // #6: SOA
generic_data_spec, // #7
generic_data_spec, // #8
generic_data_spec, // #9
generic_data_spec, // #10
generic_data_spec, // #11
{n_single_name_fields, 1, 0, single_compressible_name_fields}, // #12: PTR
generic_data_spec, // #13: HINFO
{n_double_name_fields, 2, 0, double_compressible_name_fields}, // #14:HINFO
{n_mx_fields, 1, 0, mx_fields}, // #15: MX
generic_data_spec, // #16: TXT
{n_double_name_fields, 2, 0, double_noattr_name_fields}, // 17: RP
{n_afsdb_fields, 1, 0, afsdb_fields}, // #18: AFSDB
// #19-#26
generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
generic_data_spec, // #27
{n_ipv6_fields, 0, 0, single_ipv6_fields}, // #28: AAAA
// #29-#32
generic_data_spec, generic_data_spec, generic_data_spec, generic_data_spec,
{n_srv_fields, 1, 0, srv_fields}, // #33: SRV
generic_data_spec, // #34
{n_naptr_fields, 1, 1, naptr_fields}, // #35: NAPTR
generic_data_spec, // #36
generic_data_spec, // #37
generic_data_spec, // #38
{n_single_name_fields, 1, 0, single_noattr_name_fields}, // #39 DNAME
generic_data_spec, // #40
generic_data_spec, // #41 (OPT)
generic_data_spec, // #42
generic_data_spec, // #43: DS (this is opaque for encoding purposes)
generic_data_spec, // #44: SSHFP (this is opaque for encoding purposes)
generic_data_spec, // #45
generic_data_spec, // #46: RRSIG (this is opaque for encoding purposes)
{n_nsec_fields, 1, 1, nsec_fields} // #47: NSEC
// All others can be treated as single-field variable length data, at
// least for currently supported RR types.
};
// # of entries in encode_spec_list_in
const size_t encode_spec_list_in_size =
sizeof(encode_spec_list_in) / sizeof(encode_spec_list_in[0]);
BOOST_STATIC_ASSERT(encode_spec_list_in_size == 48);
}
const RdataEncodeSpec&
getRdataEncodeSpec(const RRClass& rrclass, const RRType& rrtype) {
// Special case: for classes other than IN, we treat RDATA of RR types
// that are class-IN specific as generic opaque data.
if (rrclass != RRClass::IN() &&
(rrtype == RRType::A() || rrtype == RRType::AAAA() ||
rrtype == RRType::SRV())) {
return (generic_data_spec);
}
// Otherwise, if the type is in the pre-defined range, we use the defined
// spec; otherwise we treat it as opaque data.
const uint16_t typecode = rrtype.getCode();
if (typecode < encode_spec_list_in_size) {
return (encode_spec_list_in[rrtype.getCode()]);
}
return (generic_data_spec);
}
}
}
}
......@@ -12,7 +12,7 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include "rdata_encoder.h"
#include "rdata_serialization.h"
#include <exceptions/exceptions.h>
......@@ -28,6 +28,7 @@
#include <cassert>
#include <cstring>
#include <vector>
#include <boost/static_assert.hpp>
using namespace isc::dns;
using std::vector;
......@@ -36,6 +37,190 @@ namespace isc {
namespace datasrc {
namespace memory {
#include "rdata_serialization_priv.cc"
namespace {
// Many types of RDATA can be treated as a single-field, variable length
// field (in terms of our encoding). The following define such most general
// form of field spec.
const RdataFieldSpec generic_data_fields[] = {
{RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE}
};
const uint16_t n_generic_data_fields =
sizeof(generic_data_fields) / sizeof(RdataFieldSpec);
const RdataEncodeSpec generic_data_spec = {
n_generic_data_fields, 0, 1, generic_data_fields
};
// RDATA consist of a single IPv4 address field.
const RdataFieldSpec single_ipv4_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint32_t), NAMEATTR_NONE}
};
const uint16_t n_ipv4_fields =
sizeof(single_ipv4_fields) / sizeof(RdataFieldSpec);
// RDATA consist of a single IPv6 address field.
const RdataFieldSpec single_ipv6_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, 16, NAMEATTR_NONE} // 128bits = 16 bytes
};
const uint16_t n_ipv6_fields =
sizeof(single_ipv6_fields) / sizeof(RdataFieldSpec);
// There are several RR types that consist of a single domain name.
const RdataFieldSpec single_noattr_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
};
const RdataFieldSpec single_compressible_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE}
};
const RdataFieldSpec single_compadditional_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0,
static_cast<RdataNameAttributes>(
static_cast<unsigned int>(NAMEATTR_COMPRESSIBLE) |
static_cast<unsigned int>(NAMEATTR_ADDITIONAL))}
};
const uint16_t n_single_name_fields =
sizeof(single_noattr_name_fields) / sizeof(RdataFieldSpec);
// RDATA consisting of two names. There are some of this type.
const RdataFieldSpec double_compressible_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE}
};
const RdataFieldSpec double_noattr_name_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
};
const uint16_t n_double_name_fields =
sizeof(double_compressible_name_fields) / sizeof(RdataFieldSpec);
// SOA specific: two compressible names + 5*32-bit data
const RdataFieldSpec soa_fields[] = {
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_COMPRESSIBLE},
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint32_t) * 5, NAMEATTR_NONE}
};
const uint16_t n_soa_fields = sizeof(soa_fields) / sizeof(RdataFieldSpec);
// MX specific: 16-bit data + compressible/additional name
const RdataFieldSpec mx_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t), NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0,
static_cast<RdataNameAttributes>(
static_cast<unsigned int>(NAMEATTR_COMPRESSIBLE) |
static_cast<unsigned int>(NAMEATTR_ADDITIONAL))}
};
const uint16_t n_mx_fields = sizeof(mx_fields) / sizeof(RdataFieldSpec);
// AFSDB specific: 16-bit data + no-attribute name
const RdataFieldSpec afsdb_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t), NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
};
const uint16_t n_afsdb_fields = sizeof(afsdb_fields) / sizeof(RdataFieldSpec);
// SRV specific: 3*16-bit data + additional name
const RdataFieldSpec srv_fields[] = {
{RdataFieldSpec::FIXEDLEN_DATA, sizeof(uint16_t) * 3, NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_ADDITIONAL}
};
const uint16_t n_srv_fields = sizeof(srv_fields) / sizeof(RdataFieldSpec);
// NAPTR specific: (multi-field) variable data + (additional) name
// NAPTR requires complicated additional section handling; for now, we skip
// the additional handling completely.
const RdataFieldSpec naptr_fields[] = {
{RdataFieldSpec::VARLEN_DATA, 0, NAMEATTR_NONE},
{RdataFieldSpec::DOMAIN_NAME, 0, NAMEATTR_NONE}
};
const uint16_t n_naptr_fields = sizeof(naptr_fields) / sizeof(RdataFieldSpec);