diff --git a/bird/bird.go b/bird/bird.go index 29f1de8..ca7d005 100644 --- a/bird/bird.go +++ b/bird/bird.go @@ -217,7 +217,6 @@ func Protocols() (Parsed, bool) { for key, _ := range (*p)["protocols"].(Parsed) { parsed := (*p)["protocols"].(Parsed)[key].(Parsed) - protocol := parsed["protocol"].(string) birdProtocol := parsed["bird_protocol"].(string) @@ -269,6 +268,16 @@ func RoutesProto(protocol string) (Parsed, bool) { return RunAndParse(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 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 RoutesProtoCount(protocol string) (Parsed, bool) { cmd := routeQueryForChannel("route protocol "+protocol) + " count" return RunAndParse(GetCacheKey("RoutesProtoCount", protocol), cmd, parseRoutesCount, nil) @@ -300,24 +309,6 @@ func RoutesExport(protocol string) (Parsed, bool) { } func RoutesNoExport(protocol string) (Parsed, bool) { - // In case we have a multi table setup, we have to query - // the pipe protocol. - if ParserConf.PerPeerTables && - strings.HasPrefix(protocol, ParserConf.PeerProtocolPrefix) { - - protocolsRes, from_cache := ProtocolsBgp() - if IsSpecial(protocolsRes) { - return protocolsRes, from_cache - } - if _, ok := protocolsRes["protocols"].(Parsed)[protocol]; !ok { - return NilParse, false - } - - // Replace prefix - protocol = ParserConf.PipeProtocolPrefix + - protocol[len(ParserConf.PeerProtocolPrefix):] - } - cmd := routeQueryForChannel("route all noexport " + protocol) return RunAndParse(GetCacheKey("RoutesNoExport", protocol), cmd, parseRoutes, nil) } @@ -331,6 +322,10 @@ func RoutesTable(table string) (Parsed, bool) { return RunAndParse(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 RoutesTableCount(table string) (Parsed, bool) { return RunAndParse(GetCacheKey("RoutesTableCount", table), "route table "+table+" count", parseRoutesCount, nil) } @@ -343,85 +338,6 @@ func RoutesLookupProtocol(net string, protocol string) (Parsed, bool) { return RunAndParse(GetCacheKey("RoutesLookupProtocol", net, protocol), "route for "+net+" protocol "+protocol+" all", parseRoutes, nil) } -func RoutesPeer(peer string) (Parsed, bool) { - cmd := routeQueryForChannel("route export " + peer) - return RunAndParse(GetCacheKey("RoutesPeer", peer), cmd, parseRoutes, nil) -} - -func RoutesDump() (Parsed, bool) { - // TODO insert hook to update the cache with the route count information - if ParserConf.PerPeerTables { - return RoutesDumpPerPeerTable() - } - - return RoutesDumpSingleTable() -} - -func RoutesDumpSingleTable() (Parsed, bool) { - importedRes, cached := RunAndParse(GetCacheKey("RoutesDumpSingleTable", "imported"), routeQueryForChannel("route all"), parseRoutes, nil) - if IsSpecial(importedRes) { - return importedRes, cached - } - filteredRes, cached := RunAndParse(GetCacheKey("RoutesDumpSingleTable", "filtered"), routeQueryForChannel("route all filtered"), parseRoutes, nil) - if IsSpecial(filteredRes) { - return filteredRes, cached - } - - imported := importedRes["routes"] - filtered := filteredRes["routes"] - - result := Parsed{ - "imported": imported, - "filtered": filtered, - } - - return result, cached -} - -func RoutesDumpPerPeerTable() (Parsed, bool) { - importedRes, cached := RunAndParse(GetCacheKey("RoutesDumpPerPeerTable", "imported"), routeQueryForChannel("route all"), parseRoutes, nil) - if IsSpecial(importedRes) { - return importedRes, cached - } - imported := importedRes["routes"] - filtered := []Parsed{} - - // Get protocols with filtered routes - protocolsRes, cached := ProtocolsBgp() - if IsSpecial(protocolsRes) { - return protocolsRes, cached - } - protocols := protocolsRes["protocols"].(Parsed) - - for protocol, details := range protocols { - details := details.(Parsed) - - counters, ok := details["routes"].(Parsed) - if !ok { - continue - } - filterCount := counters["filtered"] - if filterCount == 0 { - continue // nothing to do here. - } - // Lookup filtered routes - pfilteredRes, _ := RoutesFiltered(protocol) - pfiltered, ok := pfilteredRes["routes"].([]Parsed) - if !ok { - continue // something went wrong... - } - - filtered = append(filtered, pfiltered...) - } - - result := Parsed{ - "imported": imported, - "filtered": filtered, - } - - return result, cached -} - func routeQueryForChannel(cmd string) string { status, _ := Status() if IsSpecial(status) { diff --git a/bird/config.go b/bird/config.go index 37a94c0..20c81ff 100644 --- a/bird/config.go +++ b/bird/config.go @@ -17,10 +17,7 @@ type BirdConfig struct { } type ParserConfig struct { - FilterFields []string `toml:"filter_fields"` - PerPeerTables bool `toml:"per_peer_tables"` - PeerProtocolPrefix string `toml:"peer_protocol_prefix"` - PipeProtocolPrefix string `toml:"pipe_protocol_prefix"` + FilterFields []string `toml:"filter_fields"` } type RateLimitConfig struct { diff --git a/birdwatcher.go b/birdwatcher.go index 9082660..53f152b 100644 --- a/birdwatcher.go +++ b/birdwatcher.go @@ -16,7 +16,7 @@ import ( ) //go:generate versionize -var VERSION = "1.11.0" +var VERSION = "1.13.0" func isModuleEnabled(module string, modulesEnabled []string) bool { for _, enabled := range modulesEnabled { @@ -54,9 +54,18 @@ func makeRouter(config endpoints.ServerConfig) *httprouter.Router { if isModuleEnabled("routes_protocol", whitelist) { r.GET("/routes/protocol/:protocol", endpoints.Endpoint(endpoints.ProtoRoutes)) } + if isModuleEnabled("routes_peer", whitelist) { + r.GET("/routes/peer/:peer", endpoints.Endpoint(endpoints.PeerRoutes)) + } if isModuleEnabled("routes_table", whitelist) { r.GET("/routes/table/:table", endpoints.Endpoint(endpoints.TableRoutes)) } + if isModuleEnabled("routes_table_filtered", whitelist) { + r.GET("/routes/table/:table/filtered", endpoints.Endpoint(endpoints.TableRoutesFiltered)) + } + if isModuleEnabled("routes_table_peer", whitelist) { + r.GET("/routes/table/:table/peer/:peer", endpoints.Endpoint(endpoints.TableAndPeerRoutes)) + } if isModuleEnabled("routes_count_protocol", whitelist) { r.GET("/routes/count/protocol/:protocol", endpoints.Endpoint(endpoints.ProtoCount)) } @@ -79,12 +88,13 @@ func makeRouter(config endpoints.ServerConfig) *httprouter.Router { r.GET("/route/net/:net", endpoints.Endpoint(endpoints.RouteNet)) r.GET("/route/net/:net/table/:table", endpoints.Endpoint(endpoints.RouteNetTable)) } - if isModuleEnabled("routes_peer", whitelist) { - r.GET("/routes/peer", endpoints.Endpoint(endpoints.RoutesPeer)) + if isModuleEnabled("routes_pipe_filtered_count", whitelist) { + r.GET("/routes/pipe/filtered/count", endpoints.Endpoint(endpoints.PipeRoutesFilteredCount)) } - if isModuleEnabled("routes_dump", whitelist) { - r.GET("/routes/dump", endpoints.Endpoint(endpoints.RoutesDump)) + if isModuleEnabled("routes_pipe_filtered", whitelist) { + r.GET("/routes/pipe/filtered", endpoints.Endpoint(endpoints.PipeRoutesFiltered)) } + return r } @@ -108,8 +118,6 @@ func PrintServiceInfo(conf *Config, birdConf bird.BirdConfig) { for _, m := range conf.Server.ModulesEnabled { log.Println(" -", m) } - - log.Println(" Per Peer Tables:", conf.Parser.PerPeerTables) } // MyLogger is our own log.Logger wrapper so we can customize it diff --git a/endpoints/routes.go b/endpoints/routes.go index 1dee4b3..f47f4b3 100644 --- a/endpoints/routes.go +++ b/endpoints/routes.go @@ -50,6 +50,14 @@ func TableRoutes(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { return bird.RoutesTable(ps.ByName("table")) } +func TableRoutesFiltered(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { + return bird.RoutesTableFiltered(ps.ByName("table")) +} + +func TableAndPeerRoutes(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { + return bird.RoutesTableAndPeer(ps.ByName("table"), ps.ByName("peer")) +} + func ProtoCount(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { protocol, err := ValidateProtocolParam(ps.ByName("protocol")) if err != nil { @@ -78,20 +86,21 @@ func RouteNetTable(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { return bird.RoutesLookupTable(ps.ByName("net"), ps.ByName("table")) } -func RoutesPeer(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { +func PipeRoutesFiltered(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { qs := r.URL.Query() - peerl := qs["peer"] - if len(peerl) != 1 { - return bird.Parsed{"error": "need a peer as single query parameter"}, false - } - - peer, err := ValidateProtocolParam(peerl[0]) - if err != nil { - return bird.Parsed{"error": fmt.Sprintf("%s", err)}, false - } - return bird.RoutesPeer(peer) + table := qs["table"][0] + pipe := qs["pipe"][0] + return bird.PipeRoutesFiltered(pipe, table) } -func RoutesDump(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { - return bird.RoutesDump() +func PipeRoutesFilteredCount(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { + qs := r.URL.Query() + table := qs["table"][0] + pipe := qs["pipe"][0] + address := qs["address"][0] + return bird.PipeRoutesFilteredCount(pipe, table, address) +} + +func PeerRoutes(r *http.Request, ps httprouter.Params) (bird.Parsed, bool) { + return bird.RoutesPeer(ps.ByName("peer")) } diff --git a/etc/birdwatcher/birdwatcher.conf b/etc/birdwatcher/birdwatcher.conf old mode 100644 new mode 100755 index a1cc871..863b115 --- a/etc/birdwatcher/birdwatcher.conf +++ b/etc/birdwatcher/birdwatcher.conf @@ -15,7 +15,10 @@ allow_from = [] # protocols # protocols_bgp # routes_protocol +# routes_peer # routes_table +# routes_table_filtered +# routes_table_peer # routes_count_protocol # routes_count_table # routes_count_primary @@ -23,8 +26,8 @@ allow_from = [] # routes_prefixed # routes_noexport # route_net -## high-level modules (aggregated data from multiple birdc invocations) -# routes_dump +# routes_pipe_filtered_count +# routes_pipe_filtered # routes_peer @@ -33,8 +36,14 @@ modules_enabled = ["status", "protocols_bgp", "routes_protocol", "routes_peer", + "routes_table", + "routes_table_filtered", + "routes_table_peer", + "routes_filtered", "routes_prefixed", - "routes_dump" + "routes_noexport", + "routes_pipe_filtered_count", + "routes_pipe_filtered" ] [status]