diff options
author | Satoshi Fujimoto <satoshi.fujimoto7@gmail.com> | 2017-05-18 15:34:35 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-06-05 14:24:45 +0900 |
commit | 6e9d5b56c41904fbc63928888d3437f88f05f473 (patch) | |
tree | 624e993941e6e032ba1d33d47466d95f4de0a4ba /config | |
parent | 8fd9530ff9602912c57c18faf86e4144533c1f05 (diff) |
*: Support Peer-Group Configuration
This patch enables to create peer-groups,
also supports dynamic configuration to peer-groups.
Manually set fields in neighbor configs have priority over its peer-group's config,
except some fields, like "peer-as", or "minimum-advertisement-interval" and so on.
Signed-off-by: Satoshi Fujimoto <satoshi.fujimoto7@gmail.com>
Diffstat (limited to 'config')
-rw-r--r-- | config/default.go | 91 | ||||
-rw-r--r-- | config/serve.go | 40 |
2 files changed, 128 insertions, 3 deletions
diff --git a/config/default.go b/config/default.go index 224a6218..3b0db592 100644 --- a/config/default.go +++ b/config/default.go @@ -7,6 +7,7 @@ import ( "github.com/osrg/gobgp/packet/rtr" "github.com/spf13/viper" "net" + "reflect" ) const ( @@ -15,6 +16,20 @@ const ( DEFAULT_CONNECT_RETRY = 120 ) +var forcedOverwrittenConfig = []string{ + "neighbor.config.peer-as", + "neighbor.timers.config.minimum-advertisement-interval", +} + +var configuredFields map[string]interface{} + +func RegisterConfiguredFields(addr string, n interface{}) { + if configuredFields == nil { + configuredFields = make(map[string]interface{}, 0) + } + configuredFields[addr] = n +} + func defaultAfiSafi(typ AfiSafiType, enable bool) AfiSafi { return AfiSafi{ Config: AfiSafiConfig{ @@ -255,6 +270,22 @@ func setDefaultPolicyConfigValuesWithViper(v *viper.Viper, p *PolicyDefinition) return nil } +func validatePeerGroupConfig(n *Neighbor, b *BgpConfigSet) error { + name := n.Config.PeerGroup + if name == "" { + return nil + } + for _, pg := range b.PeerGroups { + if name == pg.Config.PeerGroupName { + if pg.Config.PeerAs != 0 && n.Config.PeerAs != 0 { + return fmt.Errorf("Cannot configure remote-as for members. Peer-group AS %d.", pg.Config.PeerAs) + } + return nil + } + } + return fmt.Errorf("No such peer-group: %s", name) +} + func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { if v == nil { v = viper.New() @@ -294,6 +325,10 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { } for idx, n := range b.Neighbors { + if err := validatePeerGroupConfig(&n, b); err != nil { + return err + } + vv := viper.New() if len(list) > idx { vv.Set("neighbor", list[idx]) @@ -302,6 +337,10 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { return err } b.Neighbors[idx] = n + + if n.Config.PeerGroup != "" { + RegisterConfiguredFields(vv.Get("neighbor.config.neighbor-address").(string), list[idx]) + } } for idx, r := range b.RpkiServers { @@ -328,3 +367,55 @@ func setDefaultConfigValuesWithViper(v *viper.Viper, b *BgpConfigSet) error { return nil } + +func OverwriteNeighborConfigWithPeerGroup(c *Neighbor, pg *PeerGroup) error { + v := viper.New() + + val, ok := configuredFields[c.Config.NeighborAddress] + if !ok { + return fmt.Errorf("No such neighbor %s", c.Config.NeighborAddress) + } + v.Set("neighbor", val) + + overwriteConfig(&c.Config, &pg.Config, "neighbor.config", v) + overwriteConfig(&c.Timers.Config, &pg.Timers.Config, "neighbor.timers.config", v) + overwriteConfig(&c.Transport.Config, &pg.Transport.Config, "neighbor.transport.config", v) + overwriteConfig(&c.ErrorHandling.Config, &pg.ErrorHandling.Config, "neighbor.error-handling.config", v) + overwriteConfig(&c.LoggingOptions.Config, &pg.LoggingOptions.Config, "neighbor.logging-options.config", v) + overwriteConfig(&c.EbgpMultihop.Config, &pg.EbgpMultihop.Config, "neighbor.ebgp-multihop.config", v) + overwriteConfig(&c.RouteReflector.Config, &pg.RouteReflector.Config, "neighbor.route-reflector.config", v) + overwriteConfig(&c.AsPathOptions.Config, &pg.AsPathOptions.Config, "neighbor.as-path-options.config", v) + overwriteConfig(&c.AddPaths.Config, &pg.AddPaths.Config, "neighbor.add-paths.config", v) + overwriteConfig(&c.GracefulRestart.Config, &pg.GracefulRestart.Config, "neighbor.gradeful-restart.config", v) + overwriteConfig(&c.ApplyPolicy.Config, &pg.ApplyPolicy.Config, "neighbor.apply-policy.config", v) + overwriteConfig(&c.UseMultiplePaths.Config, &pg.UseMultiplePaths.Config, "neighbor.use-multiple-paths.config", v) + overwriteConfig(&c.RouteServer.Config, &pg.RouteServer.Config, "neighbor.route-server.config", v) + + if !v.IsSet("neighbor.afi-safis") { + c.AfiSafis = pg.AfiSafis + } + + return nil +} + +func overwriteConfig(c, pg interface{}, tagPrefix string, v *viper.Viper) { + nValue := reflect.Indirect(reflect.ValueOf(c)) + nType := reflect.Indirect(nValue).Type() + pgValue := reflect.Indirect(reflect.ValueOf(pg)) + pgType := reflect.Indirect(pgValue).Type() + + for i := 0; i < pgType.NumField(); i++ { + field := pgType.Field(i).Name + tag := tagPrefix + "." + nType.Field(i).Tag.Get("mapstructure") + if func() bool { + for _, t := range forcedOverwrittenConfig { + if t == tag { + return true + } + } + return false + }() || !v.IsSet(tag) { + nValue.FieldByName(field).Set(pgValue.FieldByName(field)) + } + } +} diff --git a/config/serve.go b/config/serve.go index eeb7cb4d..ac893ea7 100644 --- a/config/serve.go +++ b/config/serve.go @@ -83,6 +83,15 @@ func inSlice(n Neighbor, b []Neighbor) int { return -1 } +func existPeerGroup(n string, b []PeerGroup) int { + for i, nb := range b { + if nb.Config.PeerGroupName == n { + return i + } + } + return -1 +} + func ConfigSetToRoutingPolicy(c *BgpConfigSet) *RoutingPolicy { return &RoutingPolicy{ DefinedSets: c.DefinedSets, @@ -90,8 +99,34 @@ func ConfigSetToRoutingPolicy(c *BgpConfigSet) *RoutingPolicy { } } -func UpdateConfig(curC, newC *BgpConfigSet) ([]Neighbor, []Neighbor, []Neighbor, bool) { +func UpdatePeerGroupConfig(curC, newC *BgpConfigSet) ([]PeerGroup, []PeerGroup, []PeerGroup) { + addedPg := []PeerGroup{} + deletedPg := []PeerGroup{} + updatedPg := []PeerGroup{} + for _, n := range newC.PeerGroups { + if idx := existPeerGroup(n.Config.PeerGroupName, curC.PeerGroups); idx < 0 { + addedPg = append(addedPg, n) + } else if !n.Equal(&curC.PeerGroups[idx]) { + log.WithFields(log.Fields{ + "Topic": "Config", + }).Debugf("Current peer-group config:%s", curC.PeerGroups[idx]) + log.WithFields(log.Fields{ + "Topic": "Config", + }).Debugf("New peer-group config:%s", n) + updatedPg = append(updatedPg, n) + } + } + + for _, n := range curC.PeerGroups { + if existPeerGroup(n.Config.PeerGroupName, newC.PeerGroups) < 0 { + deletedPg = append(deletedPg, n) + } + } + return addedPg, deletedPg, updatedPg +} + +func UpdateNeighborConfig(curC, newC *BgpConfigSet) ([]Neighbor, []Neighbor, []Neighbor) { added := []Neighbor{} deleted := []Neighbor{} updated := []Neighbor{} @@ -115,8 +150,7 @@ func UpdateConfig(curC, newC *BgpConfigSet) ([]Neighbor, []Neighbor, []Neighbor, deleted = append(deleted, n) } } - - return added, deleted, updated, CheckPolicyDifference(ConfigSetToRoutingPolicy(curC), ConfigSetToRoutingPolicy(newC)) + return added, deleted, updated } func CheckPolicyDifference(currentPolicy *RoutingPolicy, newPolicy *RoutingPolicy) bool { |