package birdfmt import ( "bytes" "context" "fmt" "os/exec" "strings" ) // ShowProtocols runs `birdc [-s socket] show protocols all` and returns stdout (BIRD 2). func ShowProtocols(ctx context.Context, socket, birdcBin string) (string, error) { if birdcBin == "" { birdcBin = "birdc" } args := []string{"show", "protocols", "all"} if s := strings.TrimSpace(socket); s != "" { args = append([]string{"-s", s}, args...) } cmd := exec.CommandContext(ctx, birdcBin, args...) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { msg := strings.TrimSpace(stderr.String()) if msg != "" { return "", fmt.Errorf("birdc show protocols: %w: %s", err, msg) } return "", fmt.Errorf("birdc show protocols: %w", err) } return stdout.String(), nil } // CountEstablishedBGPSessions counts BGP protocol rows whose line contains "Established" // (heuristic for `birdc show protocols` / `show protocols all` output). func CountEstablishedBGPSessions(showProtocolsOutput string) int { lines := strings.Split(showProtocolsOutput, "\n") n := 0 for _, line := range lines { line = strings.TrimSpace(line) if line == "" || strings.HasPrefix(line, "name") || strings.HasPrefix(strings.ToLower(line), "table") { continue } if !isBGPProtocolSummaryRow(line) { continue } if strings.Contains(strings.ToLower(line), "established") { n++ } } return n }