summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--config/default.go91
-rw-r--r--config/serve.go40
-rw-r--r--docs/sources/configuration.md10
-rw-r--r--gobgpd/main.go28
-rw-r--r--server/peer.go20
-rw-r--r--server/server.go268
-rw-r--r--server/server_test.go81
7 files changed, 452 insertions, 86 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 {
diff --git a/docs/sources/configuration.md b/docs/sources/configuration.md
index 7403834c..67c7c167 100644
--- a/docs/sources/configuration.md
+++ b/docs/sources/configuration.md
@@ -52,6 +52,8 @@
# override global.config.as value
local-as = 1000
remove-private-as = "all"
+ # To enable peer group setting, uncomment the following
+ #peer-group = "my-peer-group"
[neighbors.as-path-options.config]
allow-own-as = 1
replace-peer-as = true
@@ -130,6 +132,14 @@
[neighbors.route-server.config]
route-server-client = true
+[[peer-groups]]
+ [peer-groups.config]
+ peer-group-name = "my-peer-group"
+ peer-as = 65000
+ [[peer-groups.afi-safis]]
+ [peer-groups.afi-safis.config]
+ afi-safi-name = "ipv4-unicast"
+
[[defined-sets.prefix-sets]]
prefix-set-name = "ps0"
[[defined-sets.prefix-sets.prefix-list]]
diff --git a/gobgpd/main.go b/gobgpd/main.go
index 91e98f6c..c80faa84 100644
--- a/gobgpd/main.go
+++ b/gobgpd/main.go
@@ -149,6 +149,7 @@ func main() {
select {
case newConfig := <-configCh:
var added, deleted, updated []config.Neighbor
+ var addedPg, deletedPg, updatedPg []config.PeerGroup
var updatePolicy bool
if c == nil {
@@ -190,6 +191,7 @@ func main() {
}
added = newConfig.Neighbors
+ addedPg = newConfig.PeerGroups
if opts.GracefulRestart {
for i, n := range added {
if n.GracefulRestart.Config.Enabled {
@@ -199,7 +201,10 @@ func main() {
}
} else {
- added, deleted, updated, updatePolicy = config.UpdateConfig(c, newConfig)
+ addedPg, deletedPg, updatedPg = config.UpdatePeerGroupConfig(c, newConfig)
+ added, deleted, updated = config.UpdateNeighborConfig(c, newConfig)
+ updatePolicy = config.CheckPolicyDifference(config.ConfigSetToRoutingPolicy(c), config.ConfigSetToRoutingPolicy(newConfig))
+
if updatePolicy {
log.Info("Policy config is updated")
p := config.ConfigSetToRoutingPolicy(newConfig)
@@ -241,7 +246,26 @@ func main() {
}
c = newConfig
}
-
+ for i, pg := range addedPg {
+ log.Infof("PeerGroup %s is added", pg.Config.PeerGroupName)
+ if err := bgpServer.AddPeerGroup(&addedPg[i]); err != nil {
+ log.Warn(err)
+ }
+ }
+ for i, pg := range deletedPg {
+ log.Infof("PeerGroup %s is deleted", pg.Config.PeerGroupName)
+ if err := bgpServer.DeletePeerGroup(&deletedPg[i]); err != nil {
+ log.Warn(err)
+ }
+ }
+ for i, pg := range updatedPg {
+ log.Infof("PeerGroup %s is updated", pg.Config.PeerGroupName)
+ u, err := bgpServer.UpdatePeerGroup(&updatedPg[i])
+ if err != nil {
+ log.Warn(err)
+ }
+ updatePolicy = updatePolicy || u
+ }
for i, p := range added {
log.Infof("Peer %v is added", p.Config.NeighborAddress)
if err := bgpServer.AddNeighbor(&added[i]); err != nil {
diff --git a/server/peer.go b/server/peer.go
index 6ead5fbe..a629a16d 100644
--- a/server/peer.go
+++ b/server/peer.go
@@ -31,6 +31,26 @@ const (
MIN_CONNECT_RETRY = 10
)
+type PeerGroup struct {
+ Conf *config.PeerGroup
+ members map[string]config.Neighbor
+}
+
+func NewPeerGroup(c *config.PeerGroup) *PeerGroup {
+ return &PeerGroup{
+ Conf: c,
+ members: make(map[string]config.Neighbor, 0),
+ }
+}
+
+func (pg *PeerGroup) AddMember(c config.Neighbor) {
+ pg.members[c.Config.NeighborAddress] = c
+}
+
+func (pg *PeerGroup) DeleteMember(c config.Neighbor) {
+ delete(pg.members, c.Config.NeighborAddress)
+}
+
type Peer struct {
tableId string
fsm *FSM
diff --git a/server/server.go b/server/server.go
index 79316daa..48af87da 100644
--- a/server/server.go
+++ b/server/server.go
@@ -92,27 +92,29 @@ type BgpServer struct {
fsmStateCh chan *FsmMsg
acceptCh chan *net.TCPConn
- mgmtCh chan *mgmtOp
- policy *table.RoutingPolicy
- listeners []*TCPListener
- neighborMap map[string]*Peer
- globalRib *table.TableManager
- roaManager *roaManager
- shutdown bool
- watcherMap map[WatchEventType][]*Watcher
- zclient *zebraClient
- bmpManager *bmpClientManager
- mrtManager *mrtManager
+ mgmtCh chan *mgmtOp
+ policy *table.RoutingPolicy
+ listeners []*TCPListener
+ neighborMap map[string]*Peer
+ peerGroupMap map[string]*PeerGroup
+ globalRib *table.TableManager
+ roaManager *roaManager
+ shutdown bool
+ watcherMap map[WatchEventType][]*Watcher
+ zclient *zebraClient
+ bmpManager *bmpClientManager
+ mrtManager *mrtManager
}
func NewBgpServer() *BgpServer {
roaManager, _ := NewROAManager(0)
s := &BgpServer{
- neighborMap: make(map[string]*Peer),
- policy: table.NewRoutingPolicy(),
- roaManager: roaManager,
- mgmtCh: make(chan *mgmtOp, 1),
- watcherMap: make(map[WatchEventType][]*Watcher),
+ neighborMap: make(map[string]*Peer),
+ peerGroupMap: make(map[string]*PeerGroup),
+ policy: table.NewRoutingPolicy(),
+ roaManager: roaManager,
+ mgmtCh: make(chan *mgmtOp, 1),
+ watcherMap: make(map[WatchEventType][]*Watcher),
}
s.bmpManager = newBmpClientManager(s)
s.mrtManager = newMrtManager(s)
@@ -1603,17 +1605,38 @@ func (s *BgpServer) GetNeighbor(address string, getAdvertised bool) (l []*config
return l
}
-func (server *BgpServer) addNeighbor(c *config.Neighbor) error {
-
- if err := config.SetDefaultNeighborConfigValues(c, server.bgpConfig.Global.Config.As); err != nil {
- return err
+func (server *BgpServer) addPeerGroup(c *config.PeerGroup) error {
+ name := c.Config.PeerGroupName
+ if _, y := server.peerGroupMap[name]; y {
+ return fmt.Errorf("Can't overwrite the existing peer-group: %s", name)
}
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Name": name,
+ }).Info("Add a peer group configuration")
+
+ server.peerGroupMap[c.Config.PeerGroupName] = NewPeerGroup(c)
+
+ return nil
+}
+
+func (server *BgpServer) addNeighbor(c *config.Neighbor) error {
addr := c.Config.NeighborAddress
if _, y := server.neighborMap[addr]; y {
return fmt.Errorf("Can't overwrite the existing peer: %s", addr)
}
+ if c.Config.PeerGroup != "" {
+ if err := config.OverwriteNeighborConfigWithPeerGroup(c, server.peerGroupMap[c.Config.PeerGroup].Conf); err != nil {
+ return err
+ }
+ }
+
+ if err := config.SetDefaultNeighborConfigValues(c, server.bgpConfig.Global.Config.As); err != nil {
+ return err
+ }
+
if vrf := c.Config.Vrf; vrf != "" {
if c.RouteServer.Config.RouteServerClient {
return fmt.Errorf("route server client can't be enslaved to VRF")
@@ -1668,18 +1691,50 @@ func (server *BgpServer) addNeighbor(c *config.Neighbor) error {
}
}
server.neighborMap[addr] = peer
+ if name := c.Config.PeerGroup; name != "" {
+ server.peerGroupMap[name].AddMember(*c)
+ }
peer.startFSMHandler(server.fsmincomingCh, server.fsmStateCh)
server.broadcastPeerState(peer, bgp.BGP_FSM_IDLE)
return nil
}
+func (s *BgpServer) AddPeerGroup(c *config.PeerGroup) error {
+ return s.mgmtOperation(func() error {
+ return s.addPeerGroup(c)
+ }, true)
+}
+
func (s *BgpServer) AddNeighbor(c *config.Neighbor) error {
return s.mgmtOperation(func() error {
return s.addNeighbor(c)
}, true)
}
+func (server *BgpServer) deletePeerGroup(pg *config.PeerGroup) error {
+ name := pg.Config.PeerGroupName
+
+ if _, y := server.peerGroupMap[name]; !y {
+ return fmt.Errorf("Can't delete a peer-group %s which does not exist", name)
+ }
+
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Name": name,
+ }).Info("Delete a peer group configuration")
+
+ delete(server.peerGroupMap, name)
+ return nil
+}
+
func (server *BgpServer) deleteNeighbor(c *config.Neighbor, code, subcode uint8) error {
+ if c.Config.PeerGroup != "" {
+ _, y := server.peerGroupMap[c.Config.PeerGroup]
+ if y {
+ server.peerGroupMap[c.Config.PeerGroup].DeleteMember(*c)
+ }
+ }
+
addr := c.Config.NeighborAddress
if intf := c.Config.NeighborInterface; intf != "" {
var err error
@@ -1742,90 +1797,141 @@ func (server *BgpServer) deleteNeighbor(c *config.Neighbor, code, subcode uint8)
return nil
}
+func (s *BgpServer) DeletePeerGroup(c *config.PeerGroup) error {
+ return s.mgmtOperation(func() error {
+ name := c.Config.PeerGroupName
+ for _, n := range s.neighborMap {
+ if n.fsm.pConf.Config.PeerGroup == name {
+ return fmt.Errorf("failed to delete peer-group %s: neighbor %s is in use", name, n.ID())
+ }
+ }
+ return s.deletePeerGroup(c)
+ }, true)
+}
+
func (s *BgpServer) DeleteNeighbor(c *config.Neighbor) error {
return s.mgmtOperation(func() error {
return s.deleteNeighbor(c, bgp.BGP_ERROR_CEASE, bgp.BGP_ERROR_SUB_PEER_DECONFIGURED)
}, true)
}
-func (s *BgpServer) UpdateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, err error) {
- err = s.mgmtOperation(func() error {
- addr := c.Config.NeighborAddress
- peer, ok := s.neighborMap[addr]
- if !ok {
- return fmt.Errorf("Neighbor that has %v doesn't exist.", addr)
+func (s *BgpServer) updatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool, err error) {
+ name := pg.Config.PeerGroupName
+
+ _, ok := s.peerGroupMap[name]
+ if !ok {
+ return false, fmt.Errorf("Peer-group %s doesn't exist.", name)
+ }
+ s.peerGroupMap[name].Conf = pg
+
+ for _, n := range s.peerGroupMap[name].members {
+ c := n
+ u, err := s.updateNeighbor(&c)
+ if err != nil {
+ return needsSoftResetIn, err
}
+ needsSoftResetIn = needsSoftResetIn || u
+ }
+ return needsSoftResetIn, nil
+}
- if !peer.fsm.pConf.ApplyPolicy.Equal(&c.ApplyPolicy) {
- log.WithFields(log.Fields{
- "Topic": "Peer",
- "Key": addr,
- }).Info("Update ApplyPolicy")
- s.policy.Reset(nil, map[string]config.ApplyPolicy{peer.ID(): c.ApplyPolicy})
- peer.fsm.pConf.ApplyPolicy = c.ApplyPolicy
- needsSoftResetIn = true
+func (s *BgpServer) UpdatePeerGroup(pg *config.PeerGroup) (needsSoftResetIn bool, err error) {
+ err = s.mgmtOperation(func() error {
+ needsSoftResetIn, err = s.updatePeerGroup(pg)
+ return err
+ }, true)
+ return needsSoftResetIn, err
+}
+
+func (s *BgpServer) updateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, err error) {
+ if c.Config.PeerGroup != "" {
+ if err := config.OverwriteNeighborConfigWithPeerGroup(c, s.peerGroupMap[c.Config.PeerGroup].Conf); err != nil {
+ return needsSoftResetIn, err
}
- original := peer.fsm.pConf
+ }
+
+ addr := c.Config.NeighborAddress
+ peer, ok := s.neighborMap[addr]
+ if !ok {
+ return needsSoftResetIn, fmt.Errorf("Neighbor that has %v doesn't exist.", addr)
+ }
+
+ if !peer.fsm.pConf.ApplyPolicy.Equal(&c.ApplyPolicy) {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": addr,
+ }).Info("Update ApplyPolicy")
+ s.policy.Reset(nil, map[string]config.ApplyPolicy{peer.ID(): c.ApplyPolicy})
+ peer.fsm.pConf.ApplyPolicy = c.ApplyPolicy
+ needsSoftResetIn = true
+ }
+ original := peer.fsm.pConf
- if !original.AsPathOptions.Config.Equal(&c.AsPathOptions.Config) {
+ if !original.AsPathOptions.Config.Equal(&c.AsPathOptions.Config) {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": peer.ID(),
+ }).Info("Update aspath options")
+ peer.fsm.pConf.AsPathOptions = c.AsPathOptions
+ needsSoftResetIn = true
+ }
+
+ if !original.Config.Equal(&c.Config) || !original.Transport.Config.Equal(&c.Transport.Config) || config.CheckAfiSafisChange(original.AfiSafis, c.AfiSafis) {
+ sub := uint8(bgp.BGP_ERROR_SUB_OTHER_CONFIGURATION_CHANGE)
+ if original.Config.AdminDown != c.Config.AdminDown {
+ sub = bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN
+ state := "Admin Down"
+ if c.Config.AdminDown == false {
+ state = "Admin Up"
+ }
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": peer.ID(),
- }).Info("Update aspath options")
- peer.fsm.pConf.AsPathOptions = c.AsPathOptions
- needsSoftResetIn = true
- }
-
- if !original.Config.Equal(&c.Config) || !original.Transport.Config.Equal(&c.Transport.Config) || config.CheckAfiSafisChange(original.AfiSafis, c.AfiSafis) {
- sub := uint8(bgp.BGP_ERROR_SUB_OTHER_CONFIGURATION_CHANGE)
- if original.Config.AdminDown != c.Config.AdminDown {
- sub = bgp.BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN
- state := "Admin Down"
- if c.Config.AdminDown == false {
- state = "Admin Up"
- }
- log.WithFields(log.Fields{
- "Topic": "Peer",
- "Key": peer.ID(),
- "State": state,
- }).Info("Update admin-state configuration")
- } else if original.Config.PeerAs != c.Config.PeerAs {
- sub = bgp.BGP_ERROR_SUB_PEER_DECONFIGURED
- }
- if err = s.deleteNeighbor(peer.fsm.pConf, bgp.BGP_ERROR_CEASE, sub); err != nil {
- log.WithFields(log.Fields{
- "Topic": "Peer",
- "Key": addr,
- }).Error(err)
- return err
- }
- err = s.addNeighbor(c)
- if err != nil {
- log.WithFields(log.Fields{
- "Topic": "Peer",
- "Key": addr,
- }).Error(err)
- }
- return err
+ "State": state,
+ }).Info("Update admin-state configuration")
+ } else if original.Config.PeerAs != c.Config.PeerAs {
+ sub = bgp.BGP_ERROR_SUB_PEER_DECONFIGURED
}
-
- if !original.Timers.Config.Equal(&c.Timers.Config) {
+ if err = s.deleteNeighbor(peer.fsm.pConf, bgp.BGP_ERROR_CEASE, sub); err != nil {
log.WithFields(log.Fields{
"Topic": "Peer",
- "Key": peer.ID(),
- }).Info("Update timer configuration")
- peer.fsm.pConf.Timers.Config = c.Timers.Config
+ "Key": addr,
+ }).Error(err)
+ return needsSoftResetIn, err
}
-
- err = peer.updatePrefixLimitConfig(c.AfiSafis)
+ err = s.addNeighbor(c)
if err != nil {
log.WithFields(log.Fields{
"Topic": "Peer",
"Key": addr,
}).Error(err)
- // rollback to original state
- peer.fsm.pConf = original
}
+ return needsSoftResetIn, err
+ }
+
+ if !original.Timers.Config.Equal(&c.Timers.Config) {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": peer.ID(),
+ }).Info("Update timer configuration")
+ peer.fsm.pConf.Timers.Config = c.Timers.Config
+ }
+
+ err = peer.updatePrefixLimitConfig(c.AfiSafis)
+ if err != nil {
+ log.WithFields(log.Fields{
+ "Topic": "Peer",
+ "Key": addr,
+ }).Error(err)
+ // rollback to original state
+ peer.fsm.pConf = original
+ }
+ return needsSoftResetIn, err
+}
+
+func (s *BgpServer) UpdateNeighbor(c *config.Neighbor) (needsSoftResetIn bool, err error) {
+ err = s.mgmtOperation(func() error {
+ needsSoftResetIn, err = s.updateNeighbor(c)
return err
}, true)
return needsSoftResetIn, err
diff --git a/server/server_test.go b/server/server_test.go
index 9caf8a62..99e63f54 100644
--- a/server/server_test.go
+++ b/server/server_test.go
@@ -343,3 +343,84 @@ func TestFilterpathWithRejectPolicy(t *testing.T) {
}
}
+
+func TestPeerGroup(test *testing.T) {
+ log.SetLevel(log.DebugLevel)
+ s := NewBgpServer()
+ go s.Serve()
+ s.Start(&config.Global{
+ Config: config.GlobalConfig{
+ As: 1,
+ RouterId: "1.1.1.1",
+ Port: 10180,
+ },
+ })
+ g := &config.PeerGroup{
+ Config: config.PeerGroupConfig{
+ PeerAs: 2,
+ PeerGroupName: "g",
+ },
+ }
+ if err := s.AddPeerGroup(g); err != nil {
+ log.Fatal(err)
+ }
+ n := &config.Neighbor{
+ Config: config.NeighborConfig{
+ NeighborAddress: "127.0.0.1",
+ PeerGroup: "g",
+ },
+ Transport: config.Transport{
+ Config: config.TransportConfig{
+ PassiveMode: true,
+ },
+ },
+ }
+ configured := map[string]interface{}{
+ "config": map[string]interface{}{
+ "neigbor-address": "127.0.0.1",
+ "peer-group": "g",
+ },
+ "transport": map[string]interface{}{
+ "config": map[string]interface{}{
+ "passive-mode": true,
+ },
+ },
+ }
+ config.RegisterConfiguredFields("127.0.0.1", configured)
+
+ if err := s.AddNeighbor(n); err != nil {
+ log.Fatal(err)
+ }
+
+ t := NewBgpServer()
+ go t.Serve()
+ t.Start(&config.Global{
+ Config: config.GlobalConfig{
+ As: 2,
+ RouterId: "2.2.2.2",
+ Port: -1,
+ },
+ })
+
+ m := &config.Neighbor{
+ Config: config.NeighborConfig{
+ NeighborAddress: "127.0.0.1",
+ PeerAs: 1,
+ },
+ Transport: config.Transport{
+ Config: config.TransportConfig{
+ RemotePort: 10180,
+ },
+ },
+ }
+ if err := t.AddNeighbor(m); err != nil {
+ log.Fatal(err)
+ }
+
+ for {
+ time.Sleep(time.Second)
+ if t.GetNeighbor("", false)[0].State.SessionState == config.SESSION_STATE_ESTABLISHED {
+ break
+ }
+ }
+}