diff options
-rw-r--r-- | cmd/gobgpd/main.go | 18 | ||||
-rw-r--r-- | pkg/config/config.go | 21 | ||||
-rw-r--r-- | pkg/config/config_test.go | 68 |
3 files changed, 101 insertions, 6 deletions
diff --git a/cmd/gobgpd/main.go b/cmd/gobgpd/main.go index 597a7df9..48eb43ac 100644 --- a/cmd/gobgpd/main.go +++ b/cmd/gobgpd/main.go @@ -181,7 +181,14 @@ func main() { "Topic": "Config", }).Info("Finished reading the config file") - currentConfig := config.ApplyInitialConfig(context.Background(), bgpServer, initialConfig, opts.GracefulRestart) + currentConfig, err := config.InitialConfig(context.Background(), bgpServer, initialConfig, opts.GracefulRestart) + if err != nil { + log.WithFields(log.Fields{ + "Topic": "Config", + "Error": err, + }).Fatalf("Failed to apply initial configuration %s", opts.ConfigFile) + } + for sig := range sigCh { if sig != syscall.SIGHUP { stopServer(bgpServer, opts.UseSdNotify) @@ -200,7 +207,14 @@ func main() { continue } - currentConfig = config.UpdateConfig(context.Background(), bgpServer, currentConfig, newConfig) + currentConfig, err = config.UpdateConfig(context.Background(), bgpServer, currentConfig, newConfig) + if err != nil { + log.WithFields(log.Fields{ + "Topic": "Config", + "Error": err, + }).Warningf("Failed to update config %s", opts.ConfigFile) + continue + } } } diff --git a/pkg/config/config.go b/pkg/config/config.go index ba205ce8..5e315094 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -13,6 +13,8 @@ import ( "github.com/osrg/gobgp/pkg/server" ) +// ReadConfigFile parses a config file into a BgpConfigSet which can be applied +// using InitialConfig and UpdateConfig. func ReadConfigFile(configFile, configType string) (*config.BgpConfigSet, error) { return config.ReadConfigfile(configFile, configType) } @@ -160,7 +162,12 @@ func updateNeighbors(ctx context.Context, bgpServer *server.BgpServer, updated [ return false } -func ApplyInitialConfig(ctx context.Context, bgpServer *server.BgpServer, newConfig *config.BgpConfigSet, isGracefulRestart bool) *config.BgpConfigSet { +// InitialConfig applies initial configuration to a pristine gobgp instance. It +// can only be called once for an instance. Subsequent changes to the +// configuration can be applied using UpdateConfig. The BgpConfigSet can be +// obtained by calling ReadConfigFile. If graceful restart behavior is desired, +// pass true for isGracefulRestart. Otherwise, pass false. +func InitialConfig(ctx context.Context, bgpServer *server.BgpServer, newConfig *config.BgpConfigSet, isGracefulRestart bool) (*config.BgpConfigSet, error) { if err := bgpServer.StartBgp(ctx, &api.StartBgpRequest{ Global: config.NewGlobalFromConfigStruct(&newConfig.Global), }); err != nil { @@ -277,10 +284,16 @@ func ApplyInitialConfig(ctx context.Context, bgpServer *server.BgpServer, newCon addPeerGroups(ctx, bgpServer, addedPg) addDynamicNeighbors(ctx, bgpServer, newConfig.DynamicNeighbors) addNeighbors(ctx, bgpServer, added) - return newConfig + return newConfig, nil } -func UpdateConfig(ctx context.Context, bgpServer *server.BgpServer, c, newConfig *config.BgpConfigSet) *config.BgpConfigSet { +// UpdateConfig updates the configuration of a running gobgp instance. +// InitialConfig must have been called once before this can be called for +// subsequent changes to config. The differences are that this call 1) does not +// hangle graceful restart and 2) requires a BgpConfigSet for the previous +// configuration so that it can compute the delta between it and the new +// config. The new BgpConfigSet can be obtained using ReadConfigFile. +func UpdateConfig(ctx context.Context, bgpServer *server.BgpServer, c, newConfig *config.BgpConfigSet) (*config.BgpConfigSet, error) { addedPg, deletedPg, updatedPg := config.UpdatePeerGroupConfig(c, newConfig) added, deleted, updated := config.UpdateNeighborConfig(c, newConfig) updatePolicy := config.CheckPolicyDifference(config.ConfigSetToRoutingPolicy(c), config.ConfigSetToRoutingPolicy(newConfig)) @@ -323,5 +336,5 @@ func UpdateConfig(ctx context.Context, bgpServer *server.BgpServer, c, newConfig log.Warn(err) } } - return newConfig + return newConfig, nil } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go new file mode 100644 index 00000000..67ffa5e7 --- /dev/null +++ b/pkg/config/config_test.go @@ -0,0 +1,68 @@ +package config + +import ( + "context" + "os" + "os/signal" + "syscall" + + "github.com/osrg/gobgp/pkg/server" +) + +// ExampleUpdateConfig shows how InitialConfig can be used without UpdateConfig +func ExampleInitialConfig() { + bgpServer := server.NewBgpServer() + go bgpServer.Serve() + + initialConfig, err := ReadConfigFile("gobgp.conf", "toml") + if err != nil { + // Handle error + return + } + + isGracefulRestart := true + _, err = InitialConfig(context.Background(), bgpServer, initialConfig, isGracefulRestart) + + if err != nil { + // Handle error + return + } +} + +// ExampleUpdateConfig shows how UpdateConfig is used in conjuction with +// InitialConfig. +func ExampleUpdateConfig() { + bgpServer := server.NewBgpServer() + go bgpServer.Serve() + + initialConfig, err := ReadConfigFile("gobgp.conf", "toml") + if err != nil { + // Handle error + return + } + + isGracefulRestart := true + currentConfig, err := InitialConfig(context.Background(), bgpServer, initialConfig, isGracefulRestart) + + if err != nil { + // Handle error + return + } + + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, syscall.SIGHUP) + + for range sigCh { + newConfig, err := ReadConfigFile("gobgp.conf", "toml") + if err != nil { + // Handle error + continue + } + + currentConfig, err = UpdateConfig(context.Background(), bgpServer, currentConfig, newConfig) + if err != nil { + // Handle error + continue + } + } +} |