Below is a java program I wrote to model this stuff. In the table, SF2
represents the number of clients that blew past twice the safety factor
(for aR+aHD+aR), SF1 represents the number of clients that blew past the
single safety factor. OF is the number of clients using the
activeRefreshOffset calculation that finished after the calculated
interval (e.g. aR+aHD+aRO). OF+s is the number of clients that finished
after the activeRefreshOffset + safetyFactor (in the first table these
are the same because of perfect responses). In the second table,
compare SF1 to OF+s - SF1 < OF+s suggesting that activeRefresh is a
better choice that activeRefreshQuery for the third term of the
equation. You can try a lot of different combinations, but I haven't
found any case where OF+s performs better that SF1.
The difference between lastStart and lAddHoldBegin represents the
retransmits after the first query. The differences between lAddHoldEnd
and lFinalQuery represent retransmits after the last normal query before
the end of the add hold down time until a valid answer was received
after the addHoldDown time expired.
Feel free to twiddle with this.
In this table, almost 1/5th of each of the clients exceeds the
activeRefreshOffset based calculation. Note that the safety factor
doesn't come into play as this specifies a "0" query failure rate.
java Test5011
Original TTL? (enter dd:hh:mm:ss) 1:4:0:0
New TTL? (enter dd:hh:mm:ss) 1:4:0:0
RRSig expiration interval? (enter dd:hh:mm:ss) 7:0:0:0
Orig TTL: 100800 seconds
New TTL: 100800 seconds
RRSig interval: 604800 seconds
QueryInterval: 50400 seconds
FastQuery: 8640 seconds
AddHoldDown: 2592000 seconds
ActiveRefreshOffset: 21600 seconds
activeRefresh + addHoldDown + activeRefresh: 2692800
Number of trials(-1 to exit) 10
Number of clients(-1 to exit) 25000
Failure rate [0 to .99999](-1 to exit) 0
Calculated safety factor: 0 (0.000000)
aR + aHD + aR + sF: 2692800
Offset calc - aR + aHD + aRO: 2664000
Offset plus safety: 2664000
Trial LastStart lAddHoldBegin lAddHoldEnd sOffset lFinalQuery SF2
SF1 OF OF+s
-----------------------------------------------------------------------------------
0 50394 50394 2671194 28800 2671194 0
0 3459 3459
1 50399 50399 2671199 28800 2671199 0
0 3576 3576
2 50399 50399 2671199 28800 2671199 0
0 3540 3540
3 50399 50399 2671199 28800 2671199 0
0 3508 3508
4 50399 50399 2671199 28800 2671199 0
0 3610 3610
5 50399 50399 2671199 28800 2671199 0
0 3544 3544
6 50398 50398 2671198 28800 2671198 0
0 3546 3546
7 50399 50399 2671199 28800 2671199 0
0 3611 3611
8 50398 50398 2671198 28800 2671198 0
0 3579 3579
9 50398 50398 2671198 28800 2671198 0
0 3517 3517
$ !-2
java Test5011
Original TTL? (enter dd:hh:mm:ss) 1:0:0:0
New TTL? (enter dd:hh:mm:ss) 1:0:0:0
RRSig expiration interval? (enter dd:hh:mm:ss) 7:0:0:0
Orig TTL: 86400 seconds
New TTL: 86400 seconds
RRSig interval: 604800 seconds
QueryInterval: 43200 seconds
FastQuery: 8640 seconds
AddHoldDown: 2592000 seconds
ActiveRefreshOffset: 0 seconds
activeRefresh + addHoldDown + activeRefresh: 2678400
Number of trials(-1 to exit) 10
Number of clients(-1 to exit) 100000
Failure rate [0 to .99999](-1 to exit) .25
Calculated safety factor: 77760 (9.000000)
aR + aHD + aR + sF: 2756160
Offset calc - aR + aHD + aRO: 2635200
Offset plus safety: 2712960
Trial LastStart lAddHoldBegin lAddHoldEnd sOffset lFinalQuery SF2
SF1 OF OF+s
-----------------------------------------------------------------------------------
0 43199 108405 2769525 0 2769525 0 1
54772 31
1 43198 95039 2729831 0 2753326 0 0
55168 26
2 43199 111816 2725266 0 2740462 0 0
54697 44
3 43199 90159 2736412 0 2745052 0 0
54882 31
4 43199 100917 2727795 0 2729947 0 0
54869 33
5 43199 94115 2726425 0 2740485 0 0
54978 23
6 43199 117523 2735443 0 2743990 0 0
55306 27
7 43198 101417 2734743 0 2743383 0 0
55006 29
8 43199 94634 2728554 0 2747760 0 0
54943 36
9 43199 85218 2727853 0 2737153 0 0
55070 33
import java.io.*;
import java.security.SecureRandom;
public class Test5011 {
static BufferedReader in = new BufferedReader(new InputStreamReader
(System.in));
public static void main (String[] args)
throws Exception {
int ttl = getResponse("Original TTL");
int newTTL = getResponse ("New TTL");
int rrsigExpire = getResponse ("RRSig expiration interval");
System.out.println();
boolean useSafetyFactor = true;
System.out.printf ("Orig TTL: %d seconds%nNew TTL: %d
seconds%nRRSig interval: %d seconds%n", ttl, newTTL, rrsigExpire);
int thirtyDays = convertToSeconds ("30:0:0:0");
int oneDay = convertToSeconds ("1:0:0:0");
int oneHour = convertToSeconds ("0:1:0:0");
int queryInterval = Math.max (oneHour, Math.min (thirtyDays/2,
Math.min (ttl/2, rrsigExpire/2)));
int fastQuery = Math.max (oneHour, Math.min (oneDay/10, Math.min
(ttl/10, rrsigExpire/10)));
int addHoldDown = Math.max (thirtyDays, newTTL);
System.out.printf ("QueryInterval: %d seconds%nFastQuery: %d
seconds%nAddHoldDown: %d seconds%n",
queryInterval, fastQuery, addHoldDown);
int activeRefreshOffset = addHoldDown % queryInterval;
System.out.printf ("ActiveRefreshOffset: %d seconds%n",
activeRefreshOffset);
System.out.printf ("activeRefresh + addHoldDown + activeRefresh:
%d%n%n",
2*queryInterval + addHoldDown);
int numberOfTrials = getInt ("Number of trials");
int numberOfClients = getInt ("Number of clients");
double queryFailureRate = getDouble ("Failure rate [0 to .99999]");
double safetyFactorMultiple = Math.ceil((Math.log
(numberOfClients)/Math.log(1.0/(queryFailureRate))));
int origSafetyFactor = fastQuery * (int)safetyFactorMultiple;
int safetyFactor = 2* fastQuery * (int)safetyFactorMultiple;
int totalSafeInterval = safetyFactor + 2* queryInterval + addHoldDown;
int totalOrigSafeInterval = origSafetyFactor + 2*queryInterval +
addHoldDown;
int offsetInterval = queryInterval + addHoldDown + activeRefreshOffset;
int offsetSafeInterval = offsetInterval + origSafetyFactor;
System.out.printf ("Calculated safety factor: %d (%.6f)%n",
origSafetyFactor, safetyFactorMultiple);
System.out.printf ("aR + aHD + aR + sF: %d%n%n",
totalOrigSafeInterval);
System.out.printf ("Offset calc - aR + aHD + aRO: %d%n",
offsetInterval);
System.out.printf ("Offset plus safety: %d%n%n", offsetSafeInterval);
SecureRandom rnd = new SecureRandom();
System.out.printf ("Trial LastStart lAddHoldBegin lAddHoldEnd
sOffset lFinalQuery SF2 SF1 OF OF+s%n"+
"-----------------------------------------------------------------------------------%n");
for (int j = 0; j < numberOfTrials; j++) {
int latestStartOffset = 0;
int latestAddHoldBegin = 0;
int latestAddHoldEnd = 0;
int latestFinalQuery = 0;
int smallestOffsetAtEndOfAddHold = queryInterval;
int numExceededSafety = 0;
int numExceedOrigSafety = 0;
int numExceedOffset = 0;
int numExceedOffsetSafe = 0;
for (int i = 0; i < numberOfClients; i++) {
// each trial
int startOffset = rnd.nextInt(queryInterval);
latestStartOffset = (startOffset > latestStartOffset) ?
startOffset : latestStartOffset;
/* Roll the dice after each query and if we roll a number < the
query failure rate, queue up a fast query and retry */
while (rnd.nextDouble () < queryFailureRate) {
startOffset += fastQuery;
}
latestAddHoldBegin = (startOffset > latestAddHoldBegin) ?
startOffset : latestAddHoldBegin;
// At beginning of add hold down period
int trialAddHoldDown = 0;
do {
startOffset += queryInterval;
trialAddHoldDown += queryInterval;
// and retransmits
while (rnd.nextDouble () < queryFailureRate) {
startOffset += fastQuery;
trialAddHoldDown += fastQuery;
}
} while (trialAddHoldDown < addHoldDown);
latestAddHoldEnd = (startOffset > latestAddHoldEnd) ? startOffset
: latestAddHoldEnd;
int holddiff = trialAddHoldDown - addHoldDown;
smallestOffsetAtEndOfAddHold = (holddiff <
smallestOffsetAtEndOfAddHold) ?
holddiff : smallestOffsetAtEndOfAddHold;
// past the end of the addHoldDown, the previous last query above
while (rnd.nextDouble () < queryFailureRate) {
startOffset += fastQuery;
}
latestFinalQuery = (startOffset > latestFinalQuery) ? startOffset
: latestFinalQuery;
if (startOffset > totalSafeInterval)
numExceededSafety++;
if (startOffset >totalOrigSafeInterval)
numExceedOrigSafety++;
if (startOffset > offsetInterval)
numExceedOffset++;
if (startOffset > offsetSafeInterval)
numExceedOffsetSafe++;
}
//System.out.printf ("Clients: %d%nLatestStartOffset
%d%nLatestAddHoldBegin: %d%nLatestAddHoldEnd: %d%nSmallest Offset:
%d%nLatestFinalQuery %d%n%n",
System.out.printf ("%-7d%-11d%-14d%-14d%-9d%-11d%-5d%-5d%-5d %-5d%n",
j,latestStartOffset, latestAddHoldBegin,
latestAddHoldEnd, smallestOffsetAtEndOfAddHold,
latestFinalQuery,
numExceededSafety,numExceedOrigSafety,numExceedOffset, numExceedOffsetSafe);
}
}
public static double getDouble (String prompt)
throws Exception {
do {
System.out.printf ("%s(-1 to exit) ", prompt);
String resp = in.readLine();
try {
double val = Double.valueOf(resp);
if (val < 0.0 || val >= 1.0)
throw new NumberFormatException ("Number out of range");
return val;
} catch (NumberFormatException ex) {
System.out.println (ex.getMessage());
}
} while (true);
}
public static int getInt (String prompt)
throws Exception {
do {
System.out.printf ("%s(-1 to exit) ", prompt);
String resp = in.readLine();
try {
int val = Integer.valueOf(resp);
if (val < 0)
System.exit(1);
return val;
} catch (NumberFormatException ex) {
System.out.println (ex.getMessage());
}
} while (true);
}
// return interval in seconds
public static int getResponse(String prompt)
throws Exception{
do {
System.out.printf ("%s? (enter dd:hh:mm:ss) ", prompt);
String resp = in.readLine();
try {
return convertToSeconds(resp);
} catch (NumberFormatException ex) {
System.out.println (ex.getMessage());
}
} while (true);
}
public static int convertToSeconds (String val)
throws NumberFormatException {
String[] comps = val.split(":");
if (comps.length != 4) {
throw new NumberFormatException ("Wrong number of components");
}
int[] conv = new int[4];
for (int i = 0; i < 4; i++) {
conv[i] = Integer.valueOf(comps[i]);
if (conv[i] < 0)
throw new NumberFormatException("Less than zero");
}
if (conv[1] > 23 || conv[2] > 60 || conv[3] > 60) {
throw new NumberFormatException ("Bad format - out of range for one
or more elements");
}
return conv[3] + conv[2] * 60 + conv[1] * 3600 + conv[0] * 86400;
}
}
_______________________________________________
DNSOP mailing list
DNSOP@ietf.org
https://www.ietf.org/mailman/listinfo/dnsop