generateRetransmitTracepoint creates the tcp_retransmit_skb tracepoint. This captures TCP retransmissions which indicate packet loss or congestion.
()
| 348 | // generateRetransmitTracepoint creates the tcp_retransmit_skb tracepoint. |
| 349 | // This captures TCP retransmissions which indicate packet loss or congestion. |
| 350 | func (g *ScriptGenerator) generateRetransmitTracepoint() string { |
| 351 | var sb strings.Builder |
| 352 | |
| 353 | sb.WriteString("tracepoint:tcp:tcp_retransmit_skb\n") |
| 354 | sb.WriteString("{\n") |
| 355 | |
| 356 | // Only process IPv4 (family == 2) |
| 357 | sb.WriteString(` if (args->family != 2) { return; } |
| 358 | |
| 359 | `) |
| 360 | |
| 361 | // Extract bytes into local vars first (required for BPF verifier) |
| 362 | if g.hasIPFilter() { |
| 363 | sb.WriteString(` // Read IP bytes into local vars for filtering |
| 364 | $s0 = args->saddr[0]; $s1 = args->saddr[1]; $s2 = args->saddr[2]; $s3 = args->saddr[3]; |
| 365 | $d0 = args->daddr[0]; $d1 = args->daddr[1]; $d2 = args->daddr[2]; $d3 = args->daddr[3]; |
| 366 | |
| 367 | `) |
| 368 | // Add IP filter using local vars |
| 369 | sb.WriteString(g.buildTCPIPFilterCheckFromLocalVars()) |
| 370 | } |
| 371 | |
| 372 | sb.WriteString(` $saddr = ntop(2, args->saddr); |
| 373 | $daddr = ntop(2, args->daddr); |
| 374 | $sport = args->sport; |
| 375 | $dport = args->dport; |
| 376 | $state = args->state; |
| 377 | |
| 378 | `) |
| 379 | |
| 380 | if g.config.OutputJSON { |
| 381 | // JSON: use numeric tcp_state to avoid BPF verifier complexity with string variables |
| 382 | // State values: 1=ESTABLISHED, 2=SYN_SENT, 3=SYN_RECV, 4=FIN_WAIT1, etc. |
| 383 | sb.WriteString(` printf("{\"time\":\"%s\",\"type\":\"RETRANS\",\"tcp_state\":%d,\"probe\":\"tcp_retransmit_skb\",\"src_ip\":\"%s\",\"src_port\":%d,\"dst_ip\":\"%s\",\"dst_port\":%d}\n", |
| 384 | strftime("%H:%M:%S", nsecs), |
| 385 | $state, |
| 386 | $saddr, $sport, |
| 387 | $daddr, $dport); |
| 388 | `) |
| 389 | } else { |
| 390 | // Table: decode TCP state to human-readable name (fixed values from include/net/tcp_states.h) |
| 391 | sb.WriteString(` $state_name = $state == 1 ? "ESTABLISHED" : |
| 392 | $state == 2 ? "SYN_SENT" : |
| 393 | $state == 3 ? "SYN_RECV" : |
| 394 | $state == 4 ? "FIN_WAIT1" : |
| 395 | $state == 5 ? "FIN_WAIT2" : |
| 396 | $state == 6 ? "TIME_WAIT" : |
| 397 | $state == 7 ? "CLOSE" : |
| 398 | $state == 8 ? "CLOSE_WAIT" : |
| 399 | $state == 9 ? "LAST_ACK" : |
| 400 | $state == 10 ? "LISTEN" : |
| 401 | $state == 11 ? "CLOSING" : |
| 402 | $state == 12 ? "NEW_SYN_RECV" : |
| 403 | "UNKNOWN"; |
| 404 | |
| 405 | printf("%-12s %-10s %-18s %-18s %-18s %s:%-5d -> %s:%-5d\n", |
| 406 | strftime("%H:%M:%S", nsecs), |
| 407 | "RETRANS", |
no test coverage detected