mirror of
https://github.com/alice-lg/birdwatcher.git
synced 2025-03-09 00:00:05 +01:00
Merge branch 'feature/show-protocols-uncached' into develop
This commit is contained in:
commit
00cc0bf706
14 changed files with 241 additions and 125 deletions
127
bird/bird.go
127
bird/bird.go
|
@ -159,12 +159,15 @@ func checkRateLimit() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func RunAndParse(key string, cmd string, parser func(io.Reader) Parsed, updateCache func(*Parsed)) (Parsed, bool) {
|
||||
if val, ok := fromCache(cmd); ok {
|
||||
return val, true
|
||||
func RunAndParse(useCache bool, key string, cmd string, parser func(io.Reader) Parsed, updateCache func(*Parsed)) (Parsed, bool) {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
if useCache {
|
||||
if val, ok := fromCache(cmd); ok {
|
||||
return val, true
|
||||
}
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
if queueGroup, queueLoaded := RunQueue.LoadOrStore(cmd, &wg); queueLoaded {
|
||||
(*queueGroup.(*sync.WaitGroup)).Wait()
|
||||
|
@ -200,13 +203,12 @@ func RunAndParse(key string, cmd string, parser func(io.Reader) Parsed, updateCa
|
|||
toCache(cmd, parsed)
|
||||
|
||||
wg.Done()
|
||||
|
||||
RunQueue.Delete(cmd)
|
||||
|
||||
return parsed, false
|
||||
}
|
||||
|
||||
func Status() (Parsed, bool) {
|
||||
func Status(useCache bool) (Parsed, bool) {
|
||||
updateParsedCache := func(p *Parsed) {
|
||||
status := (*p)["status"].(Parsed)
|
||||
|
||||
|
@ -235,11 +237,16 @@ func Status() (Parsed, bool) {
|
|||
}
|
||||
}
|
||||
|
||||
birdStatus, from_cache := RunAndParse(GetCacheKey("Status"), "status", parseStatus, updateParsedCache)
|
||||
birdStatus, from_cache := RunAndParse(useCache, GetCacheKey("Status"), "status", parseStatus, updateParsedCache)
|
||||
return birdStatus, from_cache
|
||||
}
|
||||
|
||||
func Protocols() (Parsed, bool) {
|
||||
func ProtocolsShort(useCache bool) (Parsed, bool) {
|
||||
res, from_cache := RunAndParse(useCache, GetCacheKey("ProtocolsShort"), "protocols", parseProtocolsShort, nil)
|
||||
return res, from_cache
|
||||
}
|
||||
|
||||
func Protocols(useCache bool) (Parsed, bool) {
|
||||
createMetaCache := func(p *Parsed) {
|
||||
metaProtocol := Parsed{"protocols": Parsed{"bird_protocol": Parsed{}}}
|
||||
|
||||
|
@ -258,12 +265,12 @@ func Protocols() (Parsed, bool) {
|
|||
toCache(GetCacheKey("metaProtocol"), metaProtocol)
|
||||
}
|
||||
|
||||
res, from_cache := RunAndParse(GetCacheKey("metaProtocol"), "protocols all", parseProtocols, createMetaCache)
|
||||
res, from_cache := RunAndParse(useCache, GetCacheKey("Protocols"), "protocols all", parseProtocols, createMetaCache)
|
||||
return res, from_cache
|
||||
}
|
||||
|
||||
func ProtocolsBgp() (Parsed, bool) {
|
||||
protocols, from_cache := Protocols()
|
||||
func ProtocolsBgp(useCache bool) (Parsed, bool) {
|
||||
protocols, from_cache := Protocols(useCache)
|
||||
if IsSpecial(protocols) {
|
||||
return protocols, from_cache
|
||||
}
|
||||
|
@ -282,92 +289,92 @@ func ProtocolsBgp() (Parsed, bool) {
|
|||
"cached_at": protocols["cached_at"]}, from_cache
|
||||
}
|
||||
|
||||
func Symbols() (Parsed, bool) {
|
||||
return RunAndParse(GetCacheKey("Symbols"), "symbols", parseSymbols, nil)
|
||||
func Symbols(useCache bool) (Parsed, bool) {
|
||||
return RunAndParse(useCache, GetCacheKey("Symbols"), "symbols", parseSymbols, nil)
|
||||
}
|
||||
|
||||
func RoutesPrefixed(prefix string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route " + prefix + " all")
|
||||
return RunAndParse(GetCacheKey("RoutesPrefixed", prefix), cmd, parseRoutes, nil)
|
||||
func RoutesPrefixed(useCache bool, prefix string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route "+prefix+" all")
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesPrefixed", prefix), cmd, parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesProto(protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route all protocol " + protocol)
|
||||
return RunAndParse(GetCacheKey("RoutesProto", protocol), cmd, parseRoutes, nil)
|
||||
func RoutesProto(useCache bool, protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route all protocol "+protocol)
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesProto", protocol), cmd, parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesPeer(peer string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route all where from=" + peer)
|
||||
return RunAndParse(GetCacheKey("RoutesPeer", peer), cmd, parseRoutes, nil)
|
||||
func RoutesPeer(useCache bool, peer string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route all where from="+peer)
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesPeer", peer), cmd, parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesTableAndPeer(table string, peer string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route table " + table + " all where from=" + peer)
|
||||
return RunAndParse(GetCacheKey("RoutesTableAndPeer", table, peer), cmd, parseRoutes, nil)
|
||||
func RoutesTableAndPeer(useCache bool, table string, peer string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route table "+table+" all where from="+peer)
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesTableAndPeer", table, peer), cmd, parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesProtoCount(protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route protocol "+protocol) + " count"
|
||||
return RunAndParse(GetCacheKey("RoutesProtoCount", protocol), cmd, parseRoutesCount, nil)
|
||||
func RoutesProtoCount(useCache bool, protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route protocol "+protocol) + " count"
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesProtoCount", protocol), cmd, parseRoutesCount, nil)
|
||||
}
|
||||
|
||||
func RoutesProtoPrimaryCount(protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route primary protocol "+protocol) + " count"
|
||||
return RunAndParse(GetCacheKey("RoutesProtoPrimaryCount", protocol), cmd, parseRoutesCount, nil)
|
||||
func RoutesProtoPrimaryCount(useCache bool, protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route primary protocol "+protocol) + " count"
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesProtoPrimaryCount", protocol), cmd, parseRoutesCount, nil)
|
||||
}
|
||||
|
||||
func PipeRoutesFilteredCount(pipe string, table string, neighborAddress string) (Parsed, bool) {
|
||||
func PipeRoutesFilteredCount(useCache bool, pipe string, table string, neighborAddress string) (Parsed, bool) {
|
||||
cmd := "route table " + table + " noexport " + pipe + " where from=" + neighborAddress + " count"
|
||||
return RunAndParse(GetCacheKey("PipeRoutesFilteredCount", table, pipe, neighborAddress), cmd, parseRoutesCount, nil)
|
||||
return RunAndParse(useCache, GetCacheKey("PipeRoutesFilteredCount", table, pipe, neighborAddress), cmd, parseRoutesCount, nil)
|
||||
}
|
||||
|
||||
func PipeRoutesFiltered(pipe string, table string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route table '" + table + "' noexport '" + pipe + "' all")
|
||||
return RunAndParse(GetCacheKey("PipeRoutesFiltered", table, pipe), cmd, parseRoutes, nil)
|
||||
func PipeRoutesFiltered(useCache bool, pipe string, table string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route table '"+table+"' noexport '"+pipe+"' all")
|
||||
return RunAndParse(useCache, GetCacheKey("PipeRoutesFiltered", table, pipe), cmd, parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesFiltered(protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route all filtered protocol " + protocol)
|
||||
return RunAndParse(GetCacheKey("RoutesFiltered", protocol), cmd, parseRoutes, nil)
|
||||
func RoutesFiltered(useCache bool, protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route all filtered protocol "+protocol)
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesFiltered", protocol), cmd, parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesExport(protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route all export " + protocol)
|
||||
return RunAndParse(GetCacheKey("RoutesExport", protocol), cmd, parseRoutes, nil)
|
||||
func RoutesExport(useCache bool, protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route all export "+protocol)
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesExport", protocol), cmd, parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesNoExport(protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route all noexport " + protocol)
|
||||
return RunAndParse(GetCacheKey("RoutesNoExport", protocol), cmd, parseRoutes, nil)
|
||||
func RoutesNoExport(useCache bool, protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route all noexport "+protocol)
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesNoExport", protocol), cmd, parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesExportCount(protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel("route export "+protocol) + " count"
|
||||
return RunAndParse(GetCacheKey("RoutesExportCount", protocol), cmd, parseRoutesCount, nil)
|
||||
func RoutesExportCount(useCache bool, protocol string) (Parsed, bool) {
|
||||
cmd := routeQueryForChannel(useCache, "route export "+protocol) + " count"
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesExportCount", protocol), cmd, parseRoutesCount, nil)
|
||||
}
|
||||
|
||||
func RoutesTable(table string) (Parsed, bool) {
|
||||
return RunAndParse(GetCacheKey("RoutesTable", table), "route table "+table+" all", parseRoutes, nil)
|
||||
func RoutesTable(useCache bool, table string) (Parsed, bool) {
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesTable", table), "route table "+table+" all", parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesTableFiltered(table string) (Parsed, bool) {
|
||||
return RunAndParse(GetCacheKey("RoutesTableFiltered", table), "route table "+table+" filtered", parseRoutes, nil)
|
||||
func RoutesTableFiltered(useCache bool, table string) (Parsed, bool) {
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesTableFiltered", table), "route table "+table+" filtered", parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesTableCount(table string) (Parsed, bool) {
|
||||
return RunAndParse(GetCacheKey("RoutesTableCount", table), "route table "+table+" count", parseRoutesCount, nil)
|
||||
func RoutesTableCount(useCache bool, table string) (Parsed, bool) {
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesTableCount", table), "route table "+table+" count", parseRoutesCount, nil)
|
||||
}
|
||||
|
||||
func RoutesLookupTable(net string, table string) (Parsed, bool) {
|
||||
return RunAndParse(GetCacheKey("RoutesLookupTable", net, table), "route for "+net+" table "+table+" all", parseRoutes, nil)
|
||||
func RoutesLookupTable(useCache bool, net string, table string) (Parsed, bool) {
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesLookupTable", net, table), "route for "+net+" table "+table+" all", parseRoutes, nil)
|
||||
}
|
||||
|
||||
func RoutesLookupProtocol(net string, protocol string) (Parsed, bool) {
|
||||
return RunAndParse(GetCacheKey("RoutesLookupProtocol", net, protocol), "route for "+net+" protocol "+protocol+" all", parseRoutes, nil)
|
||||
func RoutesLookupProtocol(useCache bool, net string, protocol string) (Parsed, bool) {
|
||||
return RunAndParse(useCache, GetCacheKey("RoutesLookupProtocol", net, protocol), "route for "+net+" protocol "+protocol+" all", parseRoutes, nil)
|
||||
}
|
||||
|
||||
func routeQueryForChannel(cmd string) string {
|
||||
status, _ := Status()
|
||||
func routeQueryForChannel(useCache bool, cmd string) string {
|
||||
status, _ := Status(useCache)
|
||||
if IsSpecial(status) {
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ var (
|
|||
routes *regexp.Regexp
|
||||
stringValue *regexp.Regexp
|
||||
routeChanges *regexp.Regexp
|
||||
short *regexp.Regexp
|
||||
}
|
||||
symbols struct {
|
||||
keyRx *regexp.Regexp
|
||||
|
@ -72,12 +73,13 @@ func init() {
|
|||
regex.protocol.routeChanges = regexp.MustCompile(`(Import|Export) (updates|withdraws):\s+(\d+|---)\s+(\d+|---)\s+(\d+|---)\s+(\d+|---)\s+(\d+|---)\s*$`)
|
||||
|
||||
regex.routes.startDefinition = regexp.MustCompile(`^([0-9a-f\.\:\/]+)\s+via\s+([0-9a-f\.\:]+)\s+on\s+([\w\.]+)\s+\[([\w\.:]+)\s+([0-9\-\:\s]+)(?:\s+from\s+([0-9a-f\.\:\/]+)){0,1}\]\s+(?:(\*)\s+){0,1}\((\d+)(?:\/\d+){0,1}\).*`)
|
||||
regex.protocol.short = regexp.MustCompile(`^(?:1002\-)?([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([0-9\-]+\s+[0-9\:]+?|[0-9\-]+)\s+(.*?)\s*?$`)
|
||||
regex.routes.second = regexp.MustCompile(`^\s+via\s+([0-9a-f\.\:]+)\s+on\s+([\w\.]+)\s+\[([\w\.:]+)\s+([0-9\-\:\s]+)(?:\s+from\s+([0-9a-f\.\:\/]+)){0,1}\]\s+(?:(\*)\s+){0,1}\((\d+)(?:\/\d+){0,1}\).*$`)
|
||||
regex.routes.routeType = regexp.MustCompile(`^\s+Type:\s+(.*)\s*$`)
|
||||
regex.routes.bgp = regexp.MustCompile(`^\s+BGP.(\w+):\s+(.+)\s*$`)
|
||||
regex.routes.community = regexp.MustCompile(`^\((\d+),\s*(\d+)\)`)
|
||||
regex.routes.largeCommunity = regexp.MustCompile(`^\((\d+),\s*(\d+),\s*(\d+)\)`)
|
||||
regex.routes.extendedCommunity = regexp.MustCompile(`^\(([^,]+),\s*(\d+),\s*(\d+)\)`)
|
||||
regex.routes.extendedCommunity = regexp.MustCompile(`^\(([^,]+),\s*([^,]+),\s*([^,]+)\)`)
|
||||
regex.routes.origin = regexp.MustCompile(`\([^\(]*\)\s*`)
|
||||
regex.routes.prefixBird2 = regexp.MustCompile(`^([0-9a-f\.\:\/]+)?\s+unicast\s+\[([\w\.:]+)\s+([0-9\-\:\s]+)(?:\s+from\s+([0-9a-f\.\:\/]+))?\]\s+(?:(\*)\s+)?\((\d+)(?:\/\d+)?(?:\/[^\)]*)?\).*$`)
|
||||
regex.routes.gatewayBird2 = regexp.MustCompile(`^\s+via\s+([0-9a-f\.\:]+)\s+on\s+([\w\.]+)\s*$`)
|
||||
|
@ -132,6 +134,35 @@ func parseStatus(reader io.Reader) Parsed {
|
|||
return Parsed{"status": res}
|
||||
}
|
||||
|
||||
func parseProtocolsShort(reader io.Reader) Parsed {
|
||||
res := Parsed{}
|
||||
|
||||
lines := newLineIterator(reader, false)
|
||||
for lines.next() {
|
||||
line := lines.string()
|
||||
|
||||
if specialLine(line) {
|
||||
continue
|
||||
}
|
||||
|
||||
if regex.protocol.short.MatchString(line) {
|
||||
// The header is skipped, because the regular expression does not
|
||||
// match if the "since" field does not contain digits
|
||||
matches := regex.protocol.short.FindStringSubmatch(line)
|
||||
|
||||
res[matches[1]] = Parsed{
|
||||
"proto": matches[2],
|
||||
"table": matches[3],
|
||||
"state": matches[4],
|
||||
"since": matches[5],
|
||||
"info": matches[6],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Parsed{"protocols": res}
|
||||
}
|
||||
|
||||
func parseProtocols(reader io.Reader) Parsed {
|
||||
res := Parsed{}
|
||||
|
||||
|
@ -472,7 +503,7 @@ func parseRoutesExtendedCommunities(groups []string, res Parsed) {
|
|||
for _, community := range regex.routes.origin.FindAllString(groups[2], -1) {
|
||||
if regex.routes.extendedCommunity.MatchString(community) {
|
||||
communityGroups := regex.routes.extendedCommunity.FindStringSubmatch(community)
|
||||
communities = append(communities, []interface{}{communityGroups[1], parseInt(communityGroups[2]), parseInt(communityGroups[3])})
|
||||
communities = append(communities, []interface{}{communityGroups[1], communityGroups[2], communityGroups[3]})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,26 @@ func TestParseProtocolBgp(t *testing.T) {
|
|||
fmt.Println(protocols)
|
||||
}
|
||||
|
||||
func TestParseProtocolShort(t *testing.T) {
|
||||
f, err := openFile("protocols_short.sample")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
p := parseProtocolsShort(f)
|
||||
log.Printf("%# v", pretty.Formatter(p))
|
||||
protocols := p["protocols"].(Parsed)
|
||||
|
||||
if len(protocols) != 27 {
|
||||
//log.Printf("%# v", pretty.Formatter(protocols))
|
||||
t.Fatalf("Expected 27 protocols, found: %v", len(protocols))
|
||||
}
|
||||
|
||||
fmt.Println(protocols)
|
||||
}
|
||||
|
||||
|
||||
func TestParseRoutesAllIpv4Bird1(t *testing.T) {
|
||||
runTestForIpv4WithFile("routes_bird1_ipv4.sample", t)
|
||||
}
|
||||
|
@ -149,7 +169,8 @@ func runTestForIpv4WithFile(file string, t *testing.T) {
|
|||
{9033, 65666, 9},
|
||||
},
|
||||
extendedCommunities: []interface{}{
|
||||
[]interface{}{"rt", int64(48858), int64(50)},
|
||||
[]interface{}{"rt", "42", "1234"},
|
||||
[]interface{}{"generic", "0x43000000", "0x1"},
|
||||
},
|
||||
metric: 100,
|
||||
localPref: "100",
|
||||
|
@ -170,9 +191,9 @@ func runTestForIpv4WithFile(file string, t *testing.T) {
|
|||
{9033, 65666, 9},
|
||||
},
|
||||
extendedCommunities: []interface{}{
|
||||
[]interface{}{"ro", int64(21414), int64(52001)},
|
||||
[]interface{}{"ro", int64(21414), int64(52004)},
|
||||
[]interface{}{"ro", int64(21414), int64(64515)},
|
||||
[]interface{}{"ro", "21414", "52001"},
|
||||
[]interface{}{"ro", "21414", "52004"},
|
||||
[]interface{}{"ro", "21414", "64515"},
|
||||
},
|
||||
metric: 100,
|
||||
localPref: "100",
|
||||
|
@ -193,9 +214,9 @@ func runTestForIpv4WithFile(file string, t *testing.T) {
|
|||
{9033, 65666, 9},
|
||||
},
|
||||
extendedCommunities: []interface{}{
|
||||
[]interface{}{"ro", int64(21414), int64(52001)},
|
||||
[]interface{}{"ro", int64(21414), int64(52004)},
|
||||
[]interface{}{"ro", int64(21414), int64(64515)},
|
||||
[]interface{}{"ro", "21414", "52001"},
|
||||
[]interface{}{"ro", "21414", "52004"},
|
||||
[]interface{}{"ro", "21414", "64515"},
|
||||
},
|
||||
metric: 100,
|
||||
localPref: "100",
|
||||
|
@ -216,7 +237,8 @@ func runTestForIpv4WithFile(file string, t *testing.T) {
|
|||
{9033, 65666, 9},
|
||||
},
|
||||
extendedCommunities: []interface{}{
|
||||
[]interface{}{"rt", int64(48858), int64(50)},
|
||||
[]interface{}{"rt", "42", "1234"},
|
||||
[]interface{}{"generic", "0x43000000", "0x1"},
|
||||
},
|
||||
metric: 100,
|
||||
localPref: "100",
|
||||
|
@ -312,9 +334,9 @@ func runTestForIpv6WithFile(file string, t *testing.T) {
|
|||
{48821, 0, 2100},
|
||||
},
|
||||
extendedCommunities: []interface{}{
|
||||
[]interface{}{"ro", int64(21414), int64(52001)},
|
||||
[]interface{}{"ro", int64(21414), int64(52004)},
|
||||
[]interface{}{"ro", int64(21414), int64(64515)},
|
||||
[]interface{}{"ro", "21414", "52001"},
|
||||
[]interface{}{"ro", "21414", "52004"},
|
||||
[]interface{}{"ro", "21414", "64515"},
|
||||
},
|
||||
metric: 100,
|
||||
localPref: "500",
|
||||
|
@ -335,9 +357,9 @@ func runTestForIpv6WithFile(file string, t *testing.T) {
|
|||
{48821, 0, 3100},
|
||||
},
|
||||
extendedCommunities: []interface{}{
|
||||
[]interface{}{"ro", int64(21414), int64(52001)},
|
||||
[]interface{}{"ro", int64(21414), int64(52004)},
|
||||
[]interface{}{"ro", int64(21414), int64(64515)},
|
||||
[]interface{}{"ro", "21414", "52001"},
|
||||
[]interface{}{"ro", "21414", "52004"},
|
||||
[]interface{}{"ro", "21414", "64515"},
|
||||
},
|
||||
localPref: "100",
|
||||
metric: 100,
|
||||
|
@ -358,7 +380,7 @@ func runTestForIpv6WithFile(file string, t *testing.T) {
|
|||
{48821, 0, 2100},
|
||||
},
|
||||
extendedCommunities: []interface{}{
|
||||
[]interface{}{"unknown 0x4300", int64(0), int64(1)},
|
||||
[]interface{}{"unknown 0x4300", "0", "1"},
|
||||
},
|
||||
metric: 100,
|
||||
localPref: "5000",
|
||||
|
|
|
@ -42,6 +42,9 @@ func makeRouter(config endpoints.ServerConfig) *httprouter.Router {
|
|||
if isModuleEnabled("protocols_bgp", whitelist) {
|
||||
r.GET("/protocols/bgp", endpoints.Endpoint(endpoints.Bgp))
|
||||
}
|
||||
if isModuleEnabled("protocols_short", whitelist) {
|
||||
r.GET("/protocols/short", endpoints.Endpoint(endpoints.ProtocolsShort))
|
||||
}
|
||||
if isModuleEnabled("symbols", whitelist) {
|
||||
r.GET("/symbols", endpoints.Endpoint(endpoints.Symbols))
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ package endpoints
|
|||
type ServerConfig struct {
|
||||
AllowFrom []string `toml:"allow_from"`
|
||||
ModulesEnabled []string `toml:"modules_enabled"`
|
||||
AllowUncached bool `toml:"allow_uncached"`
|
||||
|
||||
EnableTLS bool `toml:"enable_tls"`
|
||||
Crt string `toml:"crt"`
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
||||
type endpoint func(*http.Request, httprouter.Params) (bird.Parsed, bool)
|
||||
type endpoint func(*http.Request, httprouter.Params, bool) (bird.Parsed, bool)
|
||||
|
||||
var Conf ServerConfig
|
||||
|
||||
|
@ -42,6 +42,17 @@ func CheckAccess(req *http.Request) error {
|
|||
return fmt.Errorf("%s is not allowed to access this service.", ip)
|
||||
}
|
||||
|
||||
func CheckUseCache(req *http.Request) bool {
|
||||
qs := req.URL.Query()
|
||||
|
||||
if Conf.AllowUncached &&
|
||||
len(qs["uncached"]) == 1 && qs["uncached"][0] == "true" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func Endpoint(wrapped endpoint) httprouter.Handle {
|
||||
return func(w http.ResponseWriter,
|
||||
r *http.Request,
|
||||
|
@ -54,7 +65,9 @@ func Endpoint(wrapped endpoint) httprouter.Handle {
|
|||
}
|
||||
|
||||
res := make(map[string]interface{})
|
||||
ret, from_cache := wrapped(r, ps)
|
||||
|
||||
useCache := CheckUseCache(r)
|
||||
ret, from_cache := wrapped(r, ps, useCache)
|
||||
|
||||
if reflect.DeepEqual(ret, bird.NilParse) {
|
||||
w.WriteHeader(http.StatusTooManyRequests)
|
||||
|
|
|
@ -7,10 +7,14 @@ import (
|
|||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
||||
func Protocols(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
return bird.Protocols()
|
||||
func Protocols(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
return bird.Protocols(useCache)
|
||||
}
|
||||
|
||||
func Bgp(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
return bird.ProtocolsBgp()
|
||||
func Bgp(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
return bird.ProtocolsBgp(useCache)
|
||||
}
|
||||
|
||||
func ProtocolsShort(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
return bird.ProtocolsShort(useCache)
|
||||
}
|
||||
|
|
|
@ -8,34 +8,34 @@ import (
|
|||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
||||
func ProtoRoutes(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func ProtoRoutes(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
protocol, err := ValidateProtocolParam(ps.ByName("protocol"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesProto(protocol)
|
||||
return bird.RoutesProto(useCache, protocol)
|
||||
}
|
||||
|
||||
func RoutesFiltered(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func RoutesFiltered(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
protocol, err := ValidateProtocolParam(ps.ByName("protocol"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesFiltered(protocol)
|
||||
return bird.RoutesFiltered(useCache, protocol)
|
||||
}
|
||||
|
||||
func RoutesNoExport(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func RoutesNoExport(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
protocol, err := ValidateProtocolParam(ps.ByName("protocol"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesNoExport(protocol)
|
||||
return bird.RoutesNoExport(useCache, protocol)
|
||||
}
|
||||
|
||||
func RoutesPrefixed(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func RoutesPrefixed(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
qs := r.URL.Query()
|
||||
prefixl := qs["prefix"]
|
||||
if len(prefixl) != 1 {
|
||||
|
@ -47,28 +47,28 @@ func RoutesPrefixed(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
|||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesPrefixed(prefix)
|
||||
return bird.RoutesPrefixed(useCache, prefix)
|
||||
}
|
||||
|
||||
func TableRoutes(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func TableRoutes(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
table, err := ValidateProtocolParam(ps.ByName("table"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesTable(table)
|
||||
return bird.RoutesTable(useCache, table)
|
||||
}
|
||||
|
||||
func TableRoutesFiltered(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func TableRoutesFiltered(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
table, err := ValidateProtocolParam(ps.ByName("table"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesTableFiltered(table)
|
||||
return bird.RoutesTableFiltered(useCache, table)
|
||||
}
|
||||
|
||||
func TableAndPeerRoutes(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func TableAndPeerRoutes(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
table, err := ValidateProtocolParam(ps.ByName("table"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
|
@ -79,45 +79,45 @@ func TableAndPeerRoutes(r *http.Request, ps httprouter.Params) (bird.Parsed, boo
|
|||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesTableAndPeer(table, peer)
|
||||
return bird.RoutesTableAndPeer(useCache, table, peer)
|
||||
}
|
||||
|
||||
func ProtoCount(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func ProtoCount(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
protocol, err := ValidateProtocolParam(ps.ByName("protocol"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesProtoCount(protocol)
|
||||
return bird.RoutesProtoCount(useCache, protocol)
|
||||
}
|
||||
|
||||
func ProtoPrimaryCount(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func ProtoPrimaryCount(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
protocol, err := ValidateProtocolParam(ps.ByName("protocol"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
return bird.RoutesProtoPrimaryCount(protocol)
|
||||
return bird.RoutesProtoPrimaryCount(useCache, protocol)
|
||||
}
|
||||
|
||||
func TableCount(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func TableCount(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
table, err := ValidateProtocolParam(ps.ByName("table"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesTableCount(table)
|
||||
return bird.RoutesTableCount(useCache, table)
|
||||
}
|
||||
|
||||
func RouteNet(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func RouteNet(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
net, err := ValidatePrefixParam(ps.ByName("net"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesLookupTable(net, "master")
|
||||
return bird.RoutesLookupTable(useCache, net, "master")
|
||||
}
|
||||
|
||||
func RouteNetTable(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func RouteNetTable(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
net, err := ValidatePrefixParam(ps.ByName("net"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
|
@ -128,10 +128,10 @@ func RouteNetTable(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
|||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesLookupTable(net, table)
|
||||
return bird.RoutesLookupTable(useCache, net, table)
|
||||
}
|
||||
|
||||
func PipeRoutesFiltered(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func PipeRoutesFiltered(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
qs := r.URL.Query()
|
||||
|
||||
if len(qs["table"]) != 1 {
|
||||
|
@ -150,10 +150,10 @@ func PipeRoutesFiltered(r *http.Request, ps httprouter.Params) (bird.Parsed, boo
|
|||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.PipeRoutesFiltered(pipe, table)
|
||||
return bird.PipeRoutesFiltered(useCache, pipe, table)
|
||||
}
|
||||
|
||||
func PipeRoutesFilteredCount(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func PipeRoutesFilteredCount(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
qs := r.URL.Query()
|
||||
|
||||
if len(qs["table"]) != 1 {
|
||||
|
@ -180,14 +180,14 @@ func PipeRoutesFilteredCount(r *http.Request, ps httprouter.Params) (bird.Parsed
|
|||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.PipeRoutesFilteredCount(pipe, table, address)
|
||||
return bird.PipeRoutesFilteredCount(useCache, pipe, table, address)
|
||||
}
|
||||
|
||||
func PeerRoutes(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
func PeerRoutes(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
peer, err := ValidatePrefixParam(ps.ByName("peer"))
|
||||
if err != nil {
|
||||
return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false
|
||||
}
|
||||
|
||||
return bird.RoutesPeer(peer)
|
||||
return bird.RoutesPeer(useCache, peer)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,6 @@ import (
|
|||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
||||
func Status(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
return bird.Status()
|
||||
func Status(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
return bird.Status(useCache)
|
||||
}
|
||||
|
|
|
@ -7,20 +7,20 @@ import (
|
|||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
||||
func Symbols(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
return bird.Symbols()
|
||||
func Symbols(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
return bird.Symbols(useCache)
|
||||
}
|
||||
|
||||
func SymbolTables(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
val, from_cache := bird.Symbols()
|
||||
func SymbolTables(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
val, from_cache := bird.Symbols(useCache)
|
||||
if bird.IsSpecial(val) {
|
||||
return val, from_cache
|
||||
}
|
||||
return bird.Parsed{"symbols": val["symbols"].(bird.Parsed)["routing table"]}, from_cache
|
||||
}
|
||||
|
||||
func SymbolProtocols(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) {
|
||||
val, from_cache := bird.Symbols()
|
||||
func SymbolProtocols(r *http.Request, ps httprouter.Params, useCache bool) (bird.Parsed, bool) {
|
||||
val, from_cache := bird.Symbols(useCache)
|
||||
if bird.IsSpecial(val) {
|
||||
return val, from_cache
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
[server]
|
||||
# Restrict access to certain IPs. Leave empty to allow from all.
|
||||
allow_from = []
|
||||
# Allow queries that bypass the cache
|
||||
allow_uncached = false
|
||||
|
||||
# Available modules:
|
||||
## low-level modules (translation from birdc output to JSON objects)
|
||||
|
@ -14,6 +16,7 @@ allow_from = []
|
|||
# symbols_protocols
|
||||
# protocols
|
||||
# protocols_bgp
|
||||
# protocols_short
|
||||
# routes_protocol
|
||||
# routes_peer
|
||||
# routes_table
|
||||
|
@ -34,6 +37,7 @@ allow_from = []
|
|||
modules_enabled = ["status",
|
||||
"protocols",
|
||||
"protocols_bgp",
|
||||
"protocols_short",
|
||||
"routes_protocol",
|
||||
"routes_peer",
|
||||
"routes_table",
|
||||
|
|
31
test/protocols_short.sample
Normal file
31
test/protocols_short.sample
Normal file
|
@ -0,0 +1,31 @@
|
|||
BIRD 1.6.5 ready.
|
||||
Access restricted
|
||||
name proto table state since info
|
||||
device1 Device master up 2019-02-15
|
||||
pp_0097_as3856 Pipe master up 2019-02-15 => t_0097_as3856
|
||||
pb_0097_as3856 BGP t_0097_as3856 up 2019-02-15 Established
|
||||
pp_0175_as15169 Pipe master up 2019-02-15 => t_0175_as15169
|
||||
pb_0175_as15169 BGP t_0175_as15169 up 2019-02-15 Established
|
||||
pp_0026_as20940 Pipe master up 2019-02-15 => t_0026_as20940
|
||||
pb_0026_as20940 BGP t_0026_as20940 up 2019-02-15 Established
|
||||
direct1 Direct master down 2019-02-19 16:17:59
|
||||
kernel1 Kernel master down 2019-02-19 16:17:59
|
||||
M42_pch_radb Pipe master up 2019-02-19 16:17:59 => T42_pch_radb
|
||||
C42_pch_radb Pipe Collector up 2019-02-19 16:17:59 => T42_pch_radb
|
||||
R194_42 BGP T42_pch_radb up 2019-02-19 16:29:00 Established
|
||||
M3856_pch_radb Pipe master up 2019-02-19 16:17:59 => T3856_pch_radb
|
||||
C3856_pch_radb Pipe Collector up 2019-02-19 16:17:59 => T3856_pch_radb
|
||||
R195_42 BGP T3856_pch_radb up 2019-02-19 16:18:33 Established
|
||||
M112_112_ripe Pipe master up 2019-02-19 16:17:59 => T112_112_ripe
|
||||
C112_112_ripe Pipe Collector up 2019-02-19 16:17:59 => T112_112_ripe
|
||||
R195_77 BGP T112_112_ripe up 2019-02-19 16:24:31 Established
|
||||
M286_kpn_ripe Pipe master up 2019-02-19 16:17:59 => T286_kpn_ripe
|
||||
C286_kpn_ripe Pipe Collector up 2019-02-19 16:17:59 => T286_kpn_ripe
|
||||
R192_22 BGP T286_kpn_ripe up 2019-02-19 16:26:10 Established
|
||||
M553_belwue_ripe Pipe master up 2019-02-19 16:17:59 => T553_belwue_ripe
|
||||
C553_belwue_ripe Pipe Collector up 2019-02-19 16:17:59 => T553_belwue_ripe
|
||||
R192_175 BGP T553_belwue_ripe up 2019-02-19 16:18:34 Established
|
||||
R194_106 BGP T553_belwue_ripe up 2019-02-19 16:18:09 Established
|
||||
R194_205 BGP T52866_iveloz_radb start 2019-02-20 12:06:01 Idle BGP Error: Bad peer AS
|
||||
R_janus1 BGP T6695_bh_20 start 2019-02-19 16:17:59 Idle
|
||||
|
|
@ -8,7 +8,7 @@ BIRD 1.6.3 ready.
|
|||
BGP.community: (0,5464) (0,8339) (0,8741) (0,8823) (0,12387) (0,13101) (0,16097) (0,16316) (0,20546) (0,20686) (0,20723) (0,21083) (0,21385) (0,24940) (0,25504) (0,28876) (0,29545) (0,30058) (0,31103) (0,31400) (0,39090) (0,39392) (0,39912) (0,42473) (0,43957) (0,44453) (0,47297) (0,47692) (0,48200) (0,50629) (0,51191) (0,51839) (0,51852) (0,54113) (0,56719) (0,57957) (0,60517) (0,60574) (0,61303) (0,62297) (0,62336) (0,62359) (33891,33892) (33891,50673) (48793,48793) (50673,500)
|
||||
(65101,11077) (65102,11000) (65103,724) (65104,150)
|
||||
BGP.large_community: (9033, 65666, 12) (9033, 65666, 9)
|
||||
BGP.ext_community: (rt, 48858, 50)
|
||||
BGP.ext_community: (rt, 42, 1234) (generic, 0x43000000, 0x1)
|
||||
200.0.0.0/24 via 1.2.3.15 on eno7 [ID8497_AS1339 2017-06-21 08:17:31] * (100) [AS1339i]
|
||||
Type: BGP unicast univ
|
||||
BGP.origin: IGP
|
||||
|
@ -35,4 +35,4 @@ BIRD 1.6.3 ready.
|
|||
BGP.local_pref: 100
|
||||
BGP.community: (65011,3) (9033,3251)
|
||||
BGP.large_community: (9033, 65666, 12) (9033, 65666, 9)
|
||||
BGP.ext_community: (rt, 48858, 50)
|
||||
BGP.ext_community: (rt, 42, 1234) (generic, 0x43000000, 0x1)
|
||||
|
|
|
@ -9,7 +9,7 @@ BIRD 1.6.3 ready.
|
|||
BGP.community: (0,5464) (0,8339) (0,8741) (0,8823) (0,12387) (0,13101) (0,16097) (0,16316) (0,20546) (0,20686) (0,20723) (0,21083) (0,21385) (0,24940) (0,25504) (0,28876) (0,29545) (0,30058) (0,31103) (0,31400) (0,39090) (0,39392) (0,39912) (0,42473) (0,43957) (0,44453) (0,47297) (0,47692) (0,48200) (0,50629) (0,51191) (0,51839) (0,51852) (0,54113) (0,56719) (0,57957) (0,60517) (0,60574) (0,61303) (0,62297) (0,62336) (0,62359) (33891,33892) (33891,50673) (48793,48793) (50673,500)
|
||||
(65101,11077) (65102,11000) (65103,724) (65104,150)
|
||||
BGP.large_community: (9033, 65666, 12) (9033, 65666, 9)
|
||||
BGP.ext_community: (rt, 48858, 50)
|
||||
BGP.ext_community: (rt, 42, 1234) (generic, 0x43000000, 0x1)
|
||||
200.0.0.0/24 unicast [ID8497_AS1339 2017-06-21 08:17:31] * (100) [AS1339i]
|
||||
via 1.2.3.15 on eno7
|
||||
Type: BGP univ
|
||||
|
@ -39,4 +39,4 @@ BIRD 1.6.3 ready.
|
|||
BGP.local_pref: 100
|
||||
BGP.community: (65011,3) (9033,3251)
|
||||
BGP.large_community: (9033, 65666, 12) (9033, 65666, 9)
|
||||
BGP.ext_community: (rt, 48858, 50)
|
||||
BGP.ext_community: (rt, 42, 1234) (generic, 0x43000000, 0x1)
|
||||
|
|
Loading…
Add table
Reference in a new issue