]> git.ipfire.org Git - thirdparty/squid.git/commit
Happy Eyeballs: Deliver DNS resolution results to peer selection ASAP.
authorAlex Rousskov <rousskov@measurement-factory.com>
Wed, 12 Jul 2017 05:04:41 +0000 (23:04 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Wed, 12 Jul 2017 05:04:41 +0000 (23:04 -0600)
commitfd9c47d1075b4b01e9a283c2fd67c5958b5060c5
tree7c4887fabbbd8467444f486e327e23bb1fc85554
parent621f4299cbf34e3daf591d314cf1c14496d5f0d1
Happy Eyeballs: Deliver DNS resolution results to peer selection ASAP.

To make eyeballs happy, DNS code must deliver each lookup result to the
IP cache and, ultimately, to upper layers of ipcache_nbgethostbyname()
callers. This requires changing two interfaces:

1. between the DNS and the IP cache (the IDNSCB callback);
2. between the IP cache and peer selection code (the IPH callback).

The IDNSCB callback is now called after every usable A and AAAA lookup
instead of waiting for both answers. The IPH callback now has a sister
API for incremental delivery: The Dns::IpReceiver class.

To safely handle incremental delivery of IP addresses to the IP cache, I
upgraded ipcache_addrs from an equivalent of a C POD to a C++ CachedIps
container. The encapsulation allowed me to clearly separate the two IP
cache iteration APIs:

* All IPs (used by, e.g., ACL matching and host verification code) and
* just the "good" IPs (used only for peer selection for now).

CachedIps stores IPs together with their good/bad status in a single
std::vector. Eventually, the CachedIp element may be extended to store
TTL. The following implementation alternatives were considered and
rejected (at least for now) while optimizing for the "a few (and usually
just one), usually good IPs" case:

* Using std::list or std::deque storage would consume more RAM[1] for
  the common case of one (or few) IPs per name and slowed down IPs
  iteration code.
  [1] http://info.prelert.com/blog/stl-container-memory-usage
* Separating IP from its status, like the old code did, would make it
  easier to mismatch IP and its status, make it harder to add more
  metadata like per-IP TTL, and only save memory when storing many IPs
  per name.

The drawback of the selected "all IP-related info in one place" approach
is that we need smart iterators (e.g., the added GoodIpsIterator) or a
visitor API.

I added a new interface class for the incremental notification about
newly found IP addresses (Dns::IpReceiver) instead of adding second
IPH-like function pointer because we cannot safely call cbdata-protected
functions multiple times for the same cbdata object -- only
cbdataReferenceValidDone() dereferences the opaque pointer properly, and
that function cannot be called repeatedly. CbcPointer solves that
problem (but requires a class). Class methods also allow for more
precise notifications, with fewer ifs in the recipient code.

The new IpCacheLookupForwarder class hides the differences between the
old C-style IPH callbacks and the new Dns::IpReceiver. Eventually, we
may be able to move all lookup-specific data/methods into
IpCacheLookupForwarder, away from the IP cache entries where that info
is useless at best.

mgr:ipcache no longer reports "IPcache Entries In Use" but that info is
now available as "cbdata ipcache_entry" row in mgr:mem.

Do not cache IPv6 /etc/hosts addresses when IPv6 support is disabled.
This change simplified code, made it more consistent (we did not cache
AAAA records), and fixed ipcacheCycleAddr() and ipcacheMarkAllGood()
that were clearing supposed-to-be-permanent "bad (IPv6 disabled)" marks.

Also fixed two DNS TTL bugs. Squid now uses minimum TTL among all used
DNS records[2]. Old ipcacheParse() was trying to do the same but:
* could overwrite a zero TTL with a positive value
* took into account TTLs from unused record types (e.g., CNAME).
[2] Subject to *_dns_ttl limits in squid.conf, as before.

Also fixed "delete xstrdup" (i.e., malloc()ed) pointer in bracketed IP
parsing code (now moved to Ip::Address::FromHost()).

Also prohibited duplicate addresses from entering the IP cache. Allowing
duplicates may be useful for various hacks, but the IP cache code
assumes that cached IPs are unique and fails to mark bad repeated IPs.

Also fixed sending Squid Announcements to unsupported/disabled IPv6
addresses discovered via /etc/hosts.

Also slightly optimized dstdomain when dealing with IP-based host names:
The code now skips unnecessary Ip::Address to ipcache_addrs conversion.
This simplification may also help remove the ipcacheCheckNumeric() hack.
The bracketed IP parsing code was moved to Ip::Address::fromHost(). It
still needs a lot of love.
22 files changed:
src/HttpRequest.cc
src/PeerSelectState.h
src/acl/Asn.cc
src/acl/DestinationDomain.cc
src/acl/DestinationIp.cc
src/adaptation/icap/Xaction.cc
src/cbdata.cc
src/cbdata.h
src/client_side_request.cc
src/dns/forward.h
src/dns_internal.cc
src/fqdncache.cc
src/icmp/net_db.cc
src/ip/Address.cc
src/ip/Address.h
src/ipcache.cc
src/ipcache.h
src/multicast.cc
src/neighbors.cc
src/peer_select.cc
src/send-announce.cc
src/tests/stub_ipcache.cc