feat(keep-alive): add keep-alive option

This commit is contained in:
2025-09-27 21:49:17 +01:00
parent ddb0d2ca4e
commit 2240d18f0b
13 changed files with 363 additions and 619 deletions

View File

@@ -20,6 +20,7 @@ type MeasurementConfig struct {
OutputDir string
QueryType string
DNSSEC bool
KeepAlive bool
Interface string
Servers []string
}
@@ -74,9 +75,14 @@ func (r *MeasurementRunner) runMeasurement(upstream string, domains []string, qT
defer dnsClient.Close()
// Setup output files
jsonPath, pcapPath := GenerateOutputPaths(r.config.OutputDir, upstream, r.config.DNSSEC)
jsonPath, pcapPath := GenerateOutputPaths(r.config.OutputDir, upstream, r.config.DNSSEC, r.config.KeepAlive)
fmt.Printf(">>> Measuring %s (dnssec=%v) → %s\n", upstream, r.config.DNSSEC,
keepAliveStr := ""
if r.config.KeepAlive {
keepAliveStr = " (keep-alive)"
}
fmt.Printf(">>> Measuring %s (dnssec=%v%s) → %s\n", upstream, r.config.DNSSEC, keepAliveStr,
strings.TrimSuffix(strings.TrimSuffix(jsonPath, ".jsonl"), r.config.OutputDir+"/"))
// Setup packet capture
@@ -98,7 +104,10 @@ func (r *MeasurementRunner) runMeasurement(upstream string, domains []string, qT
}
func (r *MeasurementRunner) setupDNSClient(upstream string) (client.DNSClient, error) {
opts := client.Options{DNSSEC: r.config.DNSSEC}
opts := client.Options{
DNSSEC: r.config.DNSSEC,
KeepAlive: r.config.KeepAlive,
}
return client.New(upstream, opts)
}
@@ -136,7 +145,14 @@ func (r *MeasurementRunner) runQueries(dnsClient client.DNSClient, upstream stri
}
r.printQueryResult(metric)
time.Sleep(10 * time.Millisecond)
// For keep-alive connections, add smaller delays between queries
// to better utilize the persistent connection
if r.config.KeepAlive {
time.Sleep(5 * time.Millisecond)
} else {
time.Sleep(10 * time.Millisecond)
}
}
time.Sleep(100 * time.Millisecond)
@@ -154,6 +170,7 @@ func (r *MeasurementRunner) performQuery(dnsClient client.DNSClient, domain, ups
QueryType: r.config.QueryType,
Protocol: proto,
DNSSEC: r.config.DNSSEC,
KeepAlive: r.config.KeepAlive,
DNSServer: upstream,
Timestamp: time.Now(),
}
@@ -199,8 +216,14 @@ func (r *MeasurementRunner) printQueryResult(metric results.DNSMetric) {
if metric.ResponseCode == "ERROR" {
statusIcon = "✗"
}
fmt.Printf("%s %s [%s] %s %.2fms\n",
statusIcon, metric.Domain, metric.Protocol, metric.ResponseCode, metric.DurationMs)
keepAliveIndicator := ""
if metric.KeepAlive {
keepAliveIndicator = "⟷"
}
fmt.Printf("%s %s%s [%s] %s %.2fms\n",
statusIcon, metric.Domain, keepAliveIndicator, metric.Protocol, metric.ResponseCode, metric.DurationMs)
}
func (r *MeasurementRunner) readDomainsFile() ([]string, error) {

View File

@@ -12,6 +12,7 @@ type DNSMetric struct {
QueryType string `json:"query_type"`
Protocol string `json:"protocol"`
DNSSEC bool `json:"dnssec"`
KeepAlive bool `json:"keep_alive"`
DNSServer string `json:"dns_server"`
Timestamp time.Time `json:"timestamp"`
Duration int64 `json:"duration_ns"`
@@ -22,6 +23,7 @@ type DNSMetric struct {
Error string `json:"error,omitempty"`
}
// Rest stays exactly the same
type MetricsWriter struct {
encoder *json.Encoder
file *os.File

View File

@@ -8,17 +8,18 @@ import (
"time"
)
func GenerateOutputPaths(outputDir, upstream string, dnssec bool) (jsonPath, pcapPath string) {
func GenerateOutputPaths(outputDir, upstream string, dnssec, keepAlive bool) (jsonPath, pcapPath string) {
proto := DetectProtocol(upstream)
serverName := ExtractServerName(upstream)
ts := time.Now().Format("20060102_1504")
dnssecStr := map[bool]string{true: "on", false: "off"}[dnssec]
keepAliveStr := map[bool]string{true: "on", false: "off"}[keepAlive]
base := fmt.Sprintf("%s_%s_dnssec_%s_%s",
proto, sanitize(serverName), dnssecStr, ts)
base := fmt.Sprintf("%s_%s_dnssec_%s_keepalive_%s_%s",
proto, sanitize(serverName), dnssecStr, keepAliveStr, ts)
return filepath.Join(outputDir, base+".jsonl"),
filepath.Join(outputDir, base+".pcap")
filepath.Join(outputDir, base+".pcap")
}
func sanitize(s string) string {