diff --git a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/NameServer.java b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/NameServer.java index c3180c43c..616e5b329 100644 --- a/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/NameServer.java +++ b/traffic_router/core/src/main/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/NameServer.java @@ -23,7 +23,6 @@ import java.util.List; import org.apache.log4j.Logger; -import org.xbill.DNS.CNAMERecord; import org.xbill.DNS.DClass; import org.xbill.DNS.ExtendedFlags; import org.xbill.DNS.Flags; @@ -224,15 +223,22 @@ private void lookup(final Name qname, final int qtype, final InetAddress clientA addAuthority(zone, response, flags); } else if (sr.isCNAME()) { - final CNAMERecord cname = sr.getCNAME(); - final RRset cnameSet = new RRset(cname); - addRRset(qname, response, cnameSet, Section.ANSWER, flags); + /* + * This is an ugly hack to work around the answers() method not working for CNAMEs. + * A CNAME results in isSuccessful() being false, and answers() requires isSuccessful() + * to be true. Because of this, we can either use reflection (slow) or use the getNS() method, which + * returns the RRset stored internally in "data" and is not actually specific to NS records. + * Our CNAME and RRSIGs are in this RRset, so use getNS() despite its name. + * Refer to the dnsjava SetResponse code for more information. + */ + final RRset rrset = sr.getNS(); + addRRset(qname, response, rrset, Section.ANSWER, flags); /* * Allow recursive lookups for CNAME targets; the logic above allows us to * ensure that we only recurse for domains for which we are authoritative. */ - lookup(cname.getTarget(), qtype, clientAddress, zone, response, iteration + 1, flags, dnssecRequest, builder); + lookup(sr.getCNAME().getTarget(), qtype, clientAddress, zone, response, iteration + 1, flags, dnssecRequest, builder); } else if (sr.isNXDOMAIN()) { response.getHeader().setRcode(Rcode.NXDOMAIN); diff --git a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/ZoneManagerTest.java b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/ZoneManagerTest.java index 28e367fa1..edade91fe 100644 --- a/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/ZoneManagerTest.java +++ b/traffic_router/core/src/test/java/com/comcast/cdn/traffic_control/traffic_router/core/dns/ZoneManagerTest.java @@ -16,7 +16,9 @@ package com.comcast.cdn.traffic_control.traffic_router.core.dns; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileReader; @@ -95,6 +97,7 @@ public void testDynamicZoneCache() throws TextParseException, UnknownHostExcepti TrafficRouter trafficRouter = trafficRouterManager.getTrafficRouter(); CacheRegister cacheRegister = trafficRouter.getCacheRegister(); Map> edgeLocations = new HashMap>(); + Set dnsLimited = new HashSet(); for (Cache c : cacheRegister.getCacheMap().values()) { for (DeliveryServiceReference dsr : c.getDeliveryServices()) { @@ -103,6 +106,10 @@ public void testDynamicZoneCache() throws TextParseException, UnknownHostExcepti if (!ds.isDns()) continue; final String edgeName = dsr.getFqdn() + "."; + if (ds.getMaxDnsIps() > 0) { + dnsLimited.add(edgeName); + } + if (!edgeLocations.containsKey(edgeName)) { edgeLocations.put(edgeName, new HashSet()); } @@ -119,11 +126,52 @@ public void testDynamicZoneCache() throws TextParseException, UnknownHostExcepti for (String name : edgeLocations.keySet()) { for (CacheLocation location : edgeLocations.get(name)) { - final InetAddress source = netMap.get(location.getId()); // need to iterate through the CZF and submit a bunch of these into a job queue to run repeatedly/fast - final Zone zone = trafficRouter.getZone(new Name(name), Type.A, source, true, builder); - assertNotNull(zone); - //LOGGER.info(zone); + final InetAddress source = netMap.get(location.getId()); + final Name n = new Name(name); + final Map zoneTracker = new HashMap(); + final Set zones = new HashSet(); + final int seenThreshold = 5; + + while (true) { + final Zone zone = trafficRouter.getZone(n, Type.A, source, true, builder); // this should load the zone into the dynamicZoneCache + assertNotNull(zone); + + if (!zoneTracker.containsKey(zone)) { + zoneTracker.put(zone, 1); + } else { + final int count = zoneTracker.get(zone); + zoneTracker.put(zone, count + 1); + } + + if (!dnsLimited.contains(n.toString())) { + break; + } + + /* + * If we have limits on the number of records, continue building the cache + */ + boolean allSeen = true; + + for (Integer count : zoneTracker.values()) { + if (count < seenThreshold) { + allSeen = false; + break; + } + } + + if (allSeen) { + break; + } + } + + zones.addAll(zoneTracker.keySet()); + //System.out.println("Generated " + zones.size() + " zone(s) for " + n.toString() + " for cache group " + location.getId()); + + for (int i = 0; i < 500; i++) { + final Zone cachedZone = trafficRouter.getZone(n, Type.A, source, true, builder); // this should be a cache hit + assertTrue(zones.contains(cachedZone)); + } } } }