From 802a93d053ac9b9a99fd1d708e4e646550b426fc Mon Sep 17 00:00:00 2001 From: bert hubert Date: Fri, 26 Aug 2016 17:05:33 +0200 Subject: [PATCH] the all new label compression code that is 40% faster even on fast malloc. This commit has a bug with compression within records, and it will fail the tests we made for that too. --- pdns/dnswriter.cc | 245 ++++++++++++++++++++++++++++------------------ pdns/dnswriter.hh | 7 +- 2 files changed, 154 insertions(+), 98 deletions(-) diff --git a/pdns/dnswriter.cc b/pdns/dnswriter.cc index 475ca41ba..763bc2eb9 100644 --- a/pdns/dnswriter.cc +++ b/pdns/dnswriter.cc @@ -25,7 +25,8 @@ #include "dnswriter.hh" #include "misc.hh" #include "dnsparser.hh" - +#include +#include #include DNSPacketWriter::DNSPacketWriter(vector& content, const DNSName& qname, uint16_t qtype, uint16_t qclass, uint8_t opcode) @@ -46,7 +47,7 @@ DNSPacketWriter::DNSPacketWriter(vector& content, const DNSName& qname, memcpy(dptr, ptr, sizeof(dnsheader)); d_stuff=0; - + d_positions.reserve(16); xfrName(qname, false); len=d_content.size(); @@ -69,7 +70,6 @@ DNSPacketWriter::DNSPacketWriter(vector& content, const DNSName& qname, memcpy(&*i, &qclass, 2); d_stuff=0xffff; - d_labelmap.reserve(16); d_truncatemarker=d_content.size(); d_sor = 0; d_rollbackmarker = 0; @@ -205,117 +205,172 @@ void DNSPacketWriter::xfrUnquotedText(const string& text, bool lenField) d_record.insert(d_record.end(), text.c_str(), text.c_str() + text.length()); } -/* FIXME400: check that this beats a map */ -DNSPacketWriter::lmap_t::iterator find(DNSPacketWriter::lmap_t& nmap, const DNSName& name) + +static constexpr bool l_verbose=false; +uint16_t DNSPacketWriter::lookupName(const DNSName& name, uint16_t* matchLen) { - DNSPacketWriter::lmap_t::iterator ret; - for(ret=nmap.begin(); ret != nmap.end(); ++ret) - if(ret->first == name) + // iterate over the written labels, see if we find a match + const auto& raw = name.getStorage(); + + /* name might be a.root-servers.net, we need to be able to benefit from finding: + b.root-servers.net, or even: + b\xc0\x0c + */ + unsigned int bestpos=0; + *matchLen=0; + boost::container::static_vector nvect, pvect; + + for(auto riter= raw.cbegin(); riter < raw.cend(); ) { + if(!*riter) break; - return ret; -} + nvect.push_back(riter - raw.cbegin()); + riter+=*riter+1; + } + + if(l_verbose) { + cout<<"Input vector for lookup "<* source=0; + if(p < d_content.size()) + source = &d_content; + else { + source = &d_record; + p-= (d_content.size() + d_stuff); + + } + if(l_verbose) { + if(source == &d_content) { + DNSName pname((const char*)&(*source)[0], (*source).size(), p, true); // only for debugging + cout<<"Looking at '"< parts = name.getRawLabels(); - // labelparts_t parts; - // cerr<<"labelcount: "<first.toString()<<"]"<second< 253) // chopped does not include a length octet for the first label and the root label - throw MOADNSException("DNSPacketWriter::xfrName() found overly large (compressed) name"); - uint16_t offset=li->second; - offset|=0xc000; - d_record.push_back((char)(offset >> 8)); - d_record.push_back((char)(offset & 0xff)); - goto out; // skip trailing 0 in case of compression + uint16_t li=0; + uint16_t matchlen=0; + if(compress && (li=lookupName(name, &matchlen))) { + const auto& dns=name.getStorage(); + if(l_verbose) + cout<<"Found a substring of "< 16384, won't work - //cerr<<"stored ["< 64) - throw MOADNSException("DNSPacketWriter::xfrName() found overly large label in name"); - towrite.chopOff(); /* FIXME400: iterating the label vector while keeping this chopoff in sync is a hack */ + d_record.push_back((char)(offset >> 8)); + d_record.push_back((char)(offset & 0xff)); } - d_record.push_back(0); // insert root label + else { + unsigned int pos=d_content.size() + d_record.size() + d_stuff; + if(l_verbose) + cout<<"Found nothing, we are at pos "< 255) - throw MOADNSException("DNSPacketWriter::xfrName() found overly large name"); + std::unique_ptr lc; + if(d_lowerCase) + lc = make_unique(name.makeLowerCase()); - out:; + const DNSName::string_t& raw = (lc ? *lc : name).getStorage(); + if(l_verbose) + cout<<"Writing out the whole thing "< + + /** this class can be used to write DNS packets. It knows about DNS in the sense that it makes the packet header and record headers. @@ -59,8 +61,6 @@ class DNSPacketWriter : public boost::noncopyable { public: - typedef vector > lmap_t; - //! Start a DNS Packet in the vector passed, with question qname, qtype and qclass DNSPacketWriter(vector& content, const DNSName& qname, uint16_t qtype, uint16_t qclass=QClass::IN, uint8_t opcode=0); @@ -136,6 +136,8 @@ public: bool eof() { return true; } // we don't know how long the record should be private: + uint16_t lookupName(const DNSName& name, uint16_t* matchlen); + vector d_positions; // We declare 1 uint_16 in the public section, these 3 align on a 8-byte boundry uint16_t d_stuff; uint16_t d_sor; @@ -145,7 +147,6 @@ private: vector d_record; DNSName d_qname; DNSName d_recordqname; - lmap_t d_labelmap; uint32_t d_recordttl; uint16_t d_recordqtype, d_recordqclass; -- 2.50.0