Files
EvoBGP/internal/birdfmt/bgp.go
T

115 lines
3.5 KiB
Go

package birdfmt
import (
"fmt"
"strings"
)
// BGPPeerIPv4Options describes a single BGP session (BIRD 2, IPv4 AF).
type BGPPeerIPv4Options struct {
ProtocolName string // e.g. evobgp_peer_uplink
LocalIP string // e.g. 192.0.2.1
LocalASN uint32
NeighborIP string
NeighborASN uint32
// ExportFilter is a filter name, or empty for "export all".
ExportFilter string
// ImportFilter is a filter name, or empty for "import all".
ImportFilter string
}
// RenderProtocolBGPIPv4 renders a protocol bgp { … ipv4 { … } } block.
func RenderProtocolBGPIPv4(opts BGPPeerIPv4Options) (string, error) {
if strings.TrimSpace(opts.ProtocolName) == "" {
return "", fmt.Errorf("birdfmt: protocol name is required")
}
if strings.TrimSpace(opts.LocalIP) == "" || strings.TrimSpace(opts.NeighborIP) == "" {
return "", fmt.Errorf("birdfmt: local and neighbor addresses are required")
}
if opts.LocalASN == 0 || opts.NeighborASN == 0 {
return "", fmt.Errorf("birdfmt: AS numbers must be non-zero")
}
imp := "all"
if strings.TrimSpace(opts.ImportFilter) != "" {
imp = "filter " + strings.TrimSpace(opts.ImportFilter)
}
exp := "all"
if strings.TrimSpace(opts.ExportFilter) != "" {
exp = "filter " + strings.TrimSpace(opts.ExportFilter)
}
var b strings.Builder
b.WriteString("protocol bgp ")
b.WriteString(strings.TrimSpace(opts.ProtocolName))
b.WriteString(" {\n")
b.WriteString(" local ")
b.WriteString(strings.TrimSpace(opts.LocalIP))
fmt.Fprintf(&b, " as %d;\n", opts.LocalASN)
b.WriteString(" neighbor ")
b.WriteString(strings.TrimSpace(opts.NeighborIP))
fmt.Fprintf(&b, " as %d;\n", opts.NeighborASN)
b.WriteString(" ipv4 {\n")
b.WriteString(" import ")
b.WriteString(imp)
b.WriteString(";\n")
b.WriteString(" export ")
b.WriteString(exp)
b.WriteString(";\n")
b.WriteString(" };\n")
b.WriteString("}\n")
return b.String(), nil
}
// BGPPeerIPv6Options describes a BGP session for the IPv6 AF.
type BGPPeerIPv6Options struct {
ProtocolName string
LocalIP string
LocalASN uint32
NeighborIP string
NeighborASN uint32
ExportFilter string
ImportFilter string
}
// RenderProtocolBGPIPv6 renders a protocol bgp block with ipv6 { import/export }.
func RenderProtocolBGPIPv6(opts BGPPeerIPv6Options) (string, error) {
if strings.TrimSpace(opts.ProtocolName) == "" {
return "", fmt.Errorf("birdfmt: protocol name is required")
}
if strings.TrimSpace(opts.LocalIP) == "" || strings.TrimSpace(opts.NeighborIP) == "" {
return "", fmt.Errorf("birdfmt: local and neighbor addresses are required")
}
if opts.LocalASN == 0 || opts.NeighborASN == 0 {
return "", fmt.Errorf("birdfmt: AS numbers must be non-zero")
}
imp := "all"
if strings.TrimSpace(opts.ImportFilter) != "" {
imp = "filter " + strings.TrimSpace(opts.ImportFilter)
}
exp := "all"
if strings.TrimSpace(opts.ExportFilter) != "" {
exp = "filter " + strings.TrimSpace(opts.ExportFilter)
}
var b strings.Builder
b.WriteString("protocol bgp ")
b.WriteString(strings.TrimSpace(opts.ProtocolName))
b.WriteString(" {\n")
b.WriteString(" local ")
b.WriteString(strings.TrimSpace(opts.LocalIP))
fmt.Fprintf(&b, " as %d;\n", opts.LocalASN)
b.WriteString(" neighbor ")
b.WriteString(strings.TrimSpace(opts.NeighborIP))
fmt.Fprintf(&b, " as %d;\n", opts.NeighborASN)
b.WriteString(" ipv6 {\n")
b.WriteString(" import ")
b.WriteString(imp)
b.WriteString(";\n")
b.WriteString(" export ")
b.WriteString(exp)
b.WriteString(";\n")
b.WriteString(" };\n")
b.WriteString("}\n")
return b.String(), nil
}