diff --git a/client/client.go b/client/client.go index 5400755..9d91108 100644 --- a/client/client.go +++ b/client/client.go @@ -293,7 +293,7 @@ func createClient(scheme, host, port, path string, opts Options) (DNSClient, err // Janky solution but whatever // Here we rejoin them as the client wants them together // The host is not really a host but whatever - ServerStamp: fmt.Sprintf("%v://%v",scheme,host), + ServerStamp: fmt.Sprintf("%v://%v", scheme, host), DNSSEC: opts.DNSSEC, } logger.Debug("Creating DNSCrypt client with stamp") diff --git a/common/protocols/doh/doh.go b/common/protocols/doh/doh.go index ff67118..5f1a6a8 100644 --- a/common/protocols/doh/doh.go +++ b/common/protocols/doh/doh.go @@ -43,7 +43,7 @@ func New(config Config) (*Client, error) { } logger.Debug("Creating DoH client: %s:%s%s (KeepAlive: %v)", config.Host, config.Port, config.Path, config.KeepAlive) - + if config.Host == "" || config.Port == "" || config.Path == "" { logger.Error("DoH client creation failed: missing required fields") return nil, errors.New("doh: host, port, and path must not be empty") @@ -136,7 +136,7 @@ func (c *Client) Query(msg *dns.Msg) (*dns.Msg, error) { if c.config.DNSSEC { msg.SetEdns0(4096, true) } - + packedMsg, err := msg.Pack() if err != nil { logger.Error("DoH failed to pack DNS message: %v", err) @@ -152,7 +152,7 @@ func (c *Client) Query(msg *dns.Msg) (*dns.Msg, error) { httpReq.Header.Set("User-Agent", "sdns-proxy") httpReq.Header.Set("Content-Type", dnsMessageContentType) httpReq.Header.Set("Accept", dnsMessageContentType) - + // Set Connection header based on KeepAlive setting if c.config.KeepAlive { httpReq.Header.Set("Connection", "keep-alive") diff --git a/common/protocols/doq/doq.go b/common/protocols/doq/doq.go index 4f272ca..fb4a41e 100644 --- a/common/protocols/doq/doq.go +++ b/common/protocols/doq/doq.go @@ -47,7 +47,7 @@ func New(config Config) (*Client, error) { logger.Error("DoQ failed to resolve address %s:%s: %v", config.Host, config.Port, err) return nil, err } - + udpConn, err := net.ListenUDP("udp", nil) if err != nil { logger.Error("DoQ failed to create UDP connection: %v", err) diff --git a/common/protocols/dot/dot.go b/common/protocols/dot/dot.go index 6b50fff..88b3682 100644 --- a/common/protocols/dot/dot.go +++ b/common/protocols/dot/dot.go @@ -33,7 +33,7 @@ type Client struct { func New(config Config) (*Client, error) { logger.Debug("Creating DoT client: %s:%s (KeepAlive: %v)", config.Host, config.Port, config.KeepAlive) - + if config.Host == "" { logger.Error("DoT client creation failed: empty host") return nil, fmt.Errorf("dot: Host cannot be empty") @@ -73,7 +73,7 @@ func (c *Client) Close() { logger.Debug("Closing DoT client") c.connMutex.Lock() defer c.connMutex.Unlock() - + if c.conn != nil { c.conn.Close() c.conn = nil @@ -91,15 +91,15 @@ func (c *Client) ensureConnection() error { // Try to read one byte to test connection var testBuf [1]byte _, err := c.conn.Read(testBuf[:]) - + // Reset deadline c.conn.SetReadDeadline(time.Time{}) - + // If we get a timeout error, connection is still good if netErr, ok := err.(net.Error); ok && netErr.Timeout() { return nil } - + // Any other error means connection is dead logger.Debug("DoT connection test failed, reconnecting: %v", err) c.conn.Close() @@ -117,7 +117,7 @@ func (c *Client) ensureConnection() error { logger.Error("DoT connection failed to %s: %v", c.hostAndPort, err) return err } - + c.conn = conn logger.Debug("DoT connection established to %s", c.hostAndPort) return nil @@ -142,7 +142,7 @@ func (c *Client) Query(msg *dns.Msg) (*dns.Msg, error) { c.conn = nil } c.connMutex.Unlock() - + if err := c.ensureConnection(); err != nil { return nil, fmt.Errorf("dot: failed to create connection: %w", err) } @@ -175,22 +175,22 @@ func (c *Client) Query(msg *dns.Msg) (*dns.Msg, error) { if _, err := conn.Write(data); err != nil { logger.Error("DoT failed to write message to %s: %v", c.hostAndPort, err) - + // If keep-alive is enabled and write failed, try to reconnect once if c.config.KeepAlive { logger.Debug("DoT write failed with keep-alive, attempting reconnect") if reconnectErr := c.ensureConnection(); reconnectErr != nil { return nil, fmt.Errorf("dot: failed to reconnect: %w", reconnectErr) } - + c.connMutex.Lock() conn = c.conn c.connMutex.Unlock() - + if err := conn.SetWriteDeadline(time.Now().Add(c.config.WriteTimeout)); err != nil { return nil, fmt.Errorf("dot: failed to set write deadline after reconnect: %w", err) } - + if _, err := conn.Write(data); err != nil { return nil, fmt.Errorf("dot: failed to write message after reconnect: %w", err) } diff --git a/internal/qol/utils.go b/internal/qol/utils.go index 1bd0871..d3a1b63 100644 --- a/internal/qol/utils.go +++ b/internal/qol/utils.go @@ -40,18 +40,18 @@ func GenerateOutputPaths(outputDir, upstream string, dnssec, authDNSSEC, keepAli func cleanServerName(server string) string { // Map common servers to readable names serverMap := map[string]string{ - "1.1.1.1": "cloudflare", - "1.0.0.1": "cloudflare", - "cloudflare-dns.com": "cloudflare", - "one.one.one.one": "cloudflare", - "8.8.8.8": "google", - "8.8.4.4": "google", - "dns.google": "google", - "dns.google.com": "google", - "9.9.9.9": "quad9", - "149.112.112.112": "quad9", - "dns.quad9.net": "quad9", - "dns10.quad9.net": "quad9", + "1.1.1.1": "cloudflare", + "1.0.0.1": "cloudflare", + "cloudflare-dns.com": "cloudflare", + "one.one.one.one": "cloudflare", + "8.8.8.8": "google", + "8.8.4.4": "google", + "dns.google": "google", + "dns.google.com": "google", + "9.9.9.9": "quad9", + "149.112.112.112": "quad9", + "dns.quad9.net": "quad9", + "dns10.quad9.net": "quad9", "AQMAAAAAAAAAFDE0OS4xMTIuMTEyLjExMjo4NDQzIGfIR7jIdYzRICRVQ751Z0bfNN8dhMALjEcDaN-CHYY-GTIuZG5zY3J5cHQtY2VydC5xdWFkOS5uZXQ": "quad9", "208.67.222.222": "opendns", "208.67.220.220": "opendns", @@ -60,7 +60,7 @@ func cleanServerName(server string) string { "94.140.15.15": "adguard", "dns.adguard.com": "adguard", "dns.adguard-dns.com": "adguard", - "AQMAAAAAAAAAETk0LjE0MC4xNS4xNTo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20": "adguard", + "AQMAAAAAAAAAETk0LjE0MC4xNC4xNDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20": "adguard", } serverName := "" diff --git a/scripts/shell/run.sh b/scripts/shell/run.sh index cfbce04..47ac96e 100755 --- a/scripts/shell/run.sh +++ b/scripts/shell/run.sh @@ -137,11 +137,20 @@ run_with_perf() { if [[ -n "$suffix" ]]; then base_name="${name}-${suffix}" fi - local cpu_csv_file="$OUTPUT_DIR/${name%%-*}/${base_name}.cpu.csv" # e.g., results/cloudflare/dot-trust-persist.cpu.csv + local provider="${name%%-*}" + local protocol="${name#*-}" + local base_name="${protocol}" + if [[ -n "$suffix" ]]; then + base_name="${protocol}-${suffix}" + fi + local cpu_csv_file="$OUTPUT_DIR/${provider}/${base_name}.cpu.csv" + + # Create directory if needed + mkdir -p "$(dirname "$cpu_csv_file")" # Write header if needed if [[ ! -f "$cpu_csv_file" ]]; then - echo "timestamp,wall_time_seconds,instructions,cycles,peak_rss_kb" > "$cpu_csv_file" + echo "timestamp,wall_time_seconds,instructions,cycles" > "$cpu_csv_file" fi # Build command arguments @@ -156,7 +165,7 @@ run_with_perf() { if [[ "$dnssec" == "true" ]]; then cmd_args+=(--dnssec) if [[ "$auth" == "true" ]]; then - cmd_args+=(--auth-dnssec) + cmd_args+=(--authoritative-dnssec) fi fi @@ -164,31 +173,26 @@ run_with_perf() { cmd_args+=(--keep-alive) fi - # Create temp files for perf and time output + # Create temp file for perf local perf_tmp=$(mktemp) - local time_tmp=$(mktemp) - # Run with perf stat and /usr/bin/time + # Run with perf stat local timestamp=$(date -Iseconds) - sudo perf stat -e instructions,cycles \ + perf stat -e instructions,cycles \ -o "$perf_tmp" \ - /usr/bin/time -v \ - "$TOOL_PATH" run "${cmd_args[@]}" 2>"$time_tmp" || true + "$TOOL_PATH" run "${cmd_args[@]}" || true # Parse perf output local instructions=$(grep -oP '\d[\d,]*(?=\s+instructions)' "$perf_tmp" 2>/dev/null | tr -d ',' || echo "0") local cycles=$(grep -oP '\d[\d,]*(?=\s+cycles)' "$perf_tmp" 2>/dev/null | tr -d ',' || echo "0") local wall_time=$(grep -oP '\d+\.\d+(?= seconds time elapsed)' "$perf_tmp" 2>/dev/null || echo "0") - # Parse /usr/bin/time output for peak RSS - local peak_rss=$(grep "Maximum resident set size" "$time_tmp" 2>/dev/null | grep -oP '\d+' || echo "0") - # Append to CPU CSV - echo "${timestamp},${wall_time},${instructions},${cycles},${peak_rss}" >> "$cpu_csv_file" + echo "${timestamp},${wall_time},${instructions},${cycles}" >> "$cpu_csv_file" # Cleanup - rm -f "$perf_tmp" "$time_tmp" + rm -f "$perf_tmp" echo " -> CPU metrics saved to ${base_name}.cpu.csv" }