summaryrefslogtreecommitdiffhomepage
path: root/config
diff options
context:
space:
mode:
authorSatoshi Fujimoto <satoshi.fujimoto7@gmail.com>2017-05-18 15:34:35 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-06-05 14:24:45 +0900
commit6e9d5b56c41904fbc63928888d3437f88f05f473 (patch)
tree624e993941e6e032ba1d33d47466d95f4de0a4ba /config
parent8fd9530ff9602912c57c18faf86e4144533c1f05 (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.go91
-rw-r--r--config/serve.go40
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 {