AliceLG - Configurable timeout for GoBGP gRPC calls

This commit is contained in:
David Swafford 2020-07-20 10:08:01 -07:00
parent afc7baf79c
commit faae66f275
7 changed files with 104 additions and 14 deletions

View File

@ -19,7 +19,9 @@ Alice-LG is a BGP looking glass which gets its data from external APIs.
Currently Alice-LG supports the following APIs:
- [birdwatcher API](https://github.com/alice-lg/birdwatcher) for [BIRD](http://bird.network.cz/)
- [GoBGP](https://osrg.github.io/gobgp/)
### Birdwatcher
Normally you would first install the [birdwatcher API](https://github.com/alice-lg/birdwatcher) directly on the machine(s) where you run [BIRD](http://bird.network.cz/) on
and then install Alice-LG on a seperate public facing server and point her to the afore mentioned [birdwatcher API](https://github.com/alice-lg/birdwatcher).
@ -28,6 +30,9 @@ just prior to [RIPE73](https://ripe73.ripe.net/) in Madrid, Spain.
Major thanks to Barry O'Donovan who built the original [INEX Bird's Eye](https://github.com/inex/birdseye) BIRD API of which Alice-LG is a spinnoff
### GoBGP
Alice-LG supports direct integration with GoBGP instances using gRPC. See the configuration section for more detail.
## Building Alice-LG from scratch
__These examples include setting up your Go environment, if you already have set that up then you can obviously skip that__
@ -74,8 +79,9 @@ You can copy it to any of the following locations:
/etc/alice-lg/alice.conf # global
You will have to edit the configuration file as you need to point Alice-LG to the correct [APIs](https://github.com/alice-lg/birdwatcher):
You will have to edit the configuration file as you need to point Alice-LG to the correct backend source. Multiple sources can be configured.
[Birdwatcher](https://github.com/alice-lg/birdwatcher):
```ini
[source.rs1-example-v4]
name = rs1.example.com (IPv4)
@ -95,6 +101,23 @@ name = rs1.example.com (IPv6)
api = http://rs1.example.com:29186/
```
[GoBGP](https://osrg.github.io/gobgp/):
```ini
[source.rs2-example]
name = rs2.example.com
group = AMS
[source.rs2-example.gobgp]
# Host is the IP (or DNS name) and port for the remote GoBGP daemon
host = rs2.example.com:50051
# ProcessingTimeout is a timeout in seconds configured per gRPC call to a given GoBGP daemon
processing_timeout = 300
type = multi_table
peer_table_prefix = T
pipe_protocol_prefix = M
neighbors_refresh_timeout = 2
```
## Running
Launch the server by running

View File

@ -2,6 +2,9 @@ package main
import (
"testing"
"github.com/alice-lg/alice-lg/backend/sources/birdwatcher"
"github.com/alice-lg/alice-lg/backend/sources/gobgp"
)
// Test configuration loading and parsing
@ -37,6 +40,42 @@ func TestLoadConfigs(t *testing.T) {
}
}
// TestSourceConfig checks that the proper backend type was identified for each
// example routeserver
func TestSourceConfig(t *testing.T) {
config, err := loadConfig("../etc/alice-lg/alice.example.conf")
if err != nil {
t.Error("Could not load test config:", err)
}
// Get sources
rs1 := config.Sources[0] // Birdwatcher v4
rs2 := config.Sources[1] // Birdwatcher v6
rs3 := config.Sources[2] // GoBGP
nilBirdwatcherConfig := birdwatcher.Config{}
if rs1.Birdwatcher == nilBirdwatcherConfig {
t.Errorf(
"Example routeserver %s should have been identified as a birdwatcher source but was not",
rs1.Name,
)
}
if rs2.Birdwatcher == nilBirdwatcherConfig {
t.Errorf(
"Example routeserver %s should have been identified as a birdwatcher source but was not",
rs2.Name,
)
}
nilGoBGPConfig := gobgp.Config{}
if rs3.GoBGP == nilGoBGPConfig {
t.Errorf(
"Example routeserver %s should have been identified as a gobgp source but was not",
rs3.Name,
)
}
}
func TestSourceConfigDefaultsOverride(t *testing.T) {
config, err := loadConfig("../etc/alice-lg/alice.example.conf")
@ -45,8 +84,9 @@ func TestSourceConfigDefaultsOverride(t *testing.T) {
}
// Get sources
rs1 := config.Sources[0]
rs2 := config.Sources[1]
rs1 := config.Sources[0] // Birdwatcher v4
rs2 := config.Sources[1] // Birdwatcher v6
rs3 := config.Sources[2] // GoBGP
// Source 1 should be on default time
// Source 2 should have an override
@ -67,6 +107,13 @@ func TestSourceConfigDefaultsOverride(t *testing.T) {
if rs2.Birdwatcher.Timezone != "Europe/Brussels" {
t.Error("Expected 'Europe/Brussels', got", rs2.Birdwatcher.Timezone)
}
if rs3.GoBGP.ProcessingTimeout != 300 {
t.Error(
"Expected GoBGP example to set 300s 'processing_timeout', got",
rs3.GoBGP.ProcessingTimeout,
)
}
}
func TestRejectAndNoexportReasons(t *testing.T) {

View File

@ -6,6 +6,8 @@ type Config struct {
Host string `ini:"host"`
Insecure bool `ini:"insecure"`
// ProcessingTimeout is a timeout in seconds configured per gRPC call to a given GoBGP daemon
ProcessingTimeout int `ini:"processing_timeout"`
TLSCert string `ini:"tls_crt"`
TLSCommonName string `ini:"tls_common_name"`
}

View File

@ -48,7 +48,7 @@ func (gobgp *GoBGP) lookupNeighbour(neighborId string) (*gobgpapi.Peer, error) {
}
func (gobgp *GoBGP) GetNeighbours() ([]*gobgpapi.Peer, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(gobgp.config.ProcessingTimeout))
defer cancel()
peerStream, err := gobgp.client.ListPeer(ctx, &gobgpapi.ListPeerRequest{EnableAdvertised: true})
@ -144,7 +144,7 @@ func (gobgp *GoBGP) parsePathIntoRoute(path *gobgpapi.Path, prefix string) (erro
}
func (gobgp *GoBGP) GetRoutes(peer *gobgpapi.Peer, tableType gobgpapi.TableType, response *api.RoutesResponse) error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(gobgp.config.ProcessingTimeout))
defer cancel()
for _, family := range families {

View File

@ -88,7 +88,7 @@ func (gobgp *GoBGP) ExpireCaches() int {
}
func (gobgp *GoBGP) NeighboursStatus() (*api.NeighboursStatusResponse, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(gobgp.config.ProcessingTimeout))
defer cancel()
response := api.NeighboursStatusResponse{}
@ -123,7 +123,7 @@ func (gobgp *GoBGP) NeighboursStatus() (*api.NeighboursStatusResponse, error) {
}
func (gobgp *GoBGP) Status() (*api.StatusResponse, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(gobgp.config.ProcessingTimeout))
defer cancel()
resp, err := gobgp.client.GetBgp(ctx, &gobgpapi.GetBgpRequest{})
@ -138,7 +138,7 @@ func (gobgp *GoBGP) Status() (*api.StatusResponse, error) {
}
func (gobgp *GoBGP) Neighbours() (*api.NeighboursResponse, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(gobgp.config.ProcessingTimeout))
defer cancel()
response := api.NeighboursResponse{}

View File

@ -139,7 +139,7 @@ routeserver.name = RS
# Routeservers
# Birdwatcher Example
[source.rs0-example-v4]
name = rs1.example.com (IPv4)
# Optional: a group for the routeservers list
@ -158,7 +158,6 @@ neighbors_refresh_timeout = 2
# Optional:
show_last_reboot = true
[source.rs1-example-v6]
name = rs1.example.com (IPv6)
[source.rs1-example-v6.birdwatcher]
@ -177,3 +176,20 @@ neighbors_refresh_timeout = 2
servertime = 2006-01-02T15:04:05Z07:00
servertime_short = 02.01.2006
servertime_ext = Mon, 02 Jan 2006 15:04:05 -0700
# Routeservers
# GoBGP Example
[source.rs2-example]
name = rs2.example.com
group = AMS
[source.rs2-example.gobgp]
# host is the IP (or DNS name) and port for the remote GoBGP daemon
host = rs2.example.com:50051
# processing_timeout is a timeout in seconds configured per gRPC call to a given GoBGP daemon
processing_timeout = 300
type = multi_table
peer_table_prefix = T
pipe_protocol_prefix = M
neighbors_refresh_timeout = 2

2
go.mod
View File

@ -1,5 +1,7 @@
module github.com/alice-lg/alice-lg
go 1.14
require (
github.com/GeertJohan/go.rice v0.0.0-20181229193832-0af3f3b09a0a
github.com/daaku/go.zipexe v0.0.0-20150329023125-a5fe2436ffcb // indirect