diff options
author | Satoshi Fujimoto <satoshi.fujimoto7@gmail.com> | 2017-09-22 10:29:07 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-11-07 21:53:46 +0900 |
commit | 9e584acea92ba17a6792d4724efad0e51c118768 (patch) | |
tree | 32456e94ed1de8e57a97cf4a38d88ad43ee86680 | |
parent | 9d90d038a703f9e37e6fae4c1d035e889161a9c4 (diff) |
*: Support BGP Confederations (RFC 5065)
Signed-off-by: Satoshi Fujimoto <satoshi.fujimoto7@gmail.com>
-rw-r--r-- | config/default.go | 5 | ||||
-rw-r--r-- | server/server.go | 10 | ||||
-rw-r--r-- | table/destination.go | 11 | ||||
-rw-r--r-- | table/path.go | 37 | ||||
-rw-r--r-- | table/path_test.go | 10 | ||||
-rw-r--r-- | table/policy.go | 5 |
6 files changed, 62 insertions, 16 deletions
diff --git a/config/default.go b/config/default.go index f69c96aa..0cf1ef8a 100644 --- a/config/default.go +++ b/config/default.go @@ -124,6 +124,11 @@ func setDefaultNeighborConfigValuesWithViper(v *viper.Viper, n *Neighbor, g *Glo if n.Config.LocalAs == 0 { n.Config.LocalAs = g.Config.As + if !g.Confederation.Config.Enabled || n.IsConfederation(g) { + n.Config.LocalAs = g.Config.As + } else { + n.Config.LocalAs = g.Confederation.Config.Identifier + } } n.State.LocalAs = n.Config.LocalAs diff --git a/server/server.go b/server/server.go index 9de1c8ad..bcecdd59 100644 --- a/server/server.go +++ b/server/server.go @@ -720,7 +720,15 @@ func (server *BgpServer) propagateUpdate(peer *Peer, pathList []*table.Path) { dsts = rib.ProcessPaths(append(pathList, moded...)) } else { for idx, path := range pathList { - if p := server.policy.ApplyPolicy(table.GLOBAL_RIB_NAME, table.POLICY_DIRECTION_IMPORT, path, nil); p != nil { + var options *table.PolicyOptions + if peer != nil { + options = &table.PolicyOptions{ + Info: peer.fsm.peerInfo, + } + } else { + options = nil + } + if p := server.policy.ApplyPolicy(table.GLOBAL_RIB_NAME, table.POLICY_DIRECTION_IMPORT, path, options); p != nil { path = p } else { path = path.Clone(true) diff --git a/table/destination.go b/table/destination.go index 9631fc1c..5de89321 100644 --- a/table/destination.go +++ b/table/destination.go @@ -92,6 +92,7 @@ type PeerInfo struct { RouteReflectorClient bool RouteReflectorClusterID net.IP MultihopTtl uint8 + Confederation bool } func (lhs *PeerInfo) Equal(rhs *PeerInfo) bool { @@ -136,6 +137,7 @@ func NewPeerInfo(g *config.Global, p *config.Neighbor) *PeerInfo { Address: naddr.IP, RouteReflectorClusterID: id, MultihopTtl: p.EbgpMultihop.Config.MultihopTtl, + Confederation: p.IsConfederationMember(g), } } @@ -892,9 +894,12 @@ func compareByASNumber(path1, path2 *Path) *Path { log.WithFields(log.Fields{ "Topic": "Table", }).Debugf("compareByASNumber -- p1Asn: %d, p2Asn: %d", path1.GetSource().AS, path2.GetSource().AS) - // If one path is from ibgp peer and another is from ebgp peer, take the ebgp path - if path1.IsIBGP() != path2.IsIBGP() { - if path1.IsIBGP() { + // Path from confederation member should be treated as internal (IBGP learned) path. + isIBGP1 := path1.GetSource().Confederation || path1.IsIBGP() + isIBGP2 := path2.GetSource().Confederation || path2.IsIBGP() + // If one path is from ibgp peer and another is from ebgp peer, take the ebgp path. + if isIBGP1 != isIBGP2 { + if isIBGP1 { return path2 } return path1 diff --git a/table/path.go b/table/path.go index e192a770..d6f6e217 100644 --- a/table/path.go +++ b/table/path.go @@ -268,7 +268,11 @@ func UpdatePathAttrs(global *config.Global, peer *config.Neighbor, info *PeerInf path.RemovePrivateAS(peer.Config.LocalAs, peer.State.RemovePrivateAs) // AS_PATH handling - path.PrependAsn(peer.Config.LocalAs, 1) + confed := peer.IsConfederationMember(global) + path.PrependAsn(peer.Config.LocalAs, 1, confed) + if !confed { + path.removeConfedAs() + } // MED Handling if med := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC); med != nil && !path.IsLocal() { @@ -288,7 +292,7 @@ func UpdatePathAttrs(global *config.Global, peer *config.Neighbor, info *PeerInf // if the path has AS_PATH path attribute, don't modify it. // if not, attach *empty* AS_PATH path attribute. if nh := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); nh == nil { - path.PrependAsn(0, 0) + path.PrependAsn(0, 0, false) } // For iBGP peers we are required to send local-pref attribute @@ -711,6 +715,8 @@ func (path *Path) getAsListofSpecificType(getAsSeq, getAsSet bool) []uint32 { // PrependAsn prepends AS number. // This function updates the AS_PATH attribute as follows. +// (If the peer is in the confederation member AS, +// replace AS_SEQUENCE in the following sentence with AS_CONFED_SEQUENCE.) // 1) if the first path segment of the AS_PATH is of type // AS_SEQUENCE, the local system prepends the specified AS num as // the last element of the sequence (put it in the left-most @@ -729,7 +735,13 @@ func (path *Path) getAsListofSpecificType(getAsSeq, getAsSet bool) []uint32 { // 3) if the AS_PATH is empty, the local system creates a path // segment of type AS_SEQUENCE, places the specified AS number // into that segment, and places that segment into the AS_PATH. -func (path *Path) PrependAsn(asn uint32, repeat uint8) { +func (path *Path) PrependAsn(asn uint32, repeat uint8, confed bool) { + var segType uint8 + if confed { + segType = bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ + } else { + segType = bgp.BGP_ASPATH_ATTR_TYPE_SEQ + } original := path.GetAsPath() @@ -747,7 +759,7 @@ func (path *Path) PrependAsn(asn uint32, repeat uint8) { if len(asPath.Value) > 0 { fst := asPath.Value[0].(*bgp.As4PathParam) - if fst.Type == bgp.BGP_ASPATH_ATTR_TYPE_SEQ { + if fst.Type == segType { if len(fst.AS)+int(repeat) > 255 { repeat = uint8(255 - len(fst.AS)) } @@ -758,7 +770,7 @@ func (path *Path) PrependAsn(asn uint32, repeat uint8) { } if len(asns) > 0 { - p := bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, asns) + p := bgp.NewAs4PathParam(segType, asns) asPath.Value = append([]bgp.AsPathParamInterface{p}, asPath.Value...) } path.setPathAttr(asPath) @@ -797,6 +809,21 @@ func (path *Path) RemovePrivateAS(localAS uint32, option config.RemovePrivateAsO return } +func (path *Path) removeConfedAs() { + original := path.GetAsPath() + if original == nil { + return + } + newAsParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) + for _, v := range original.Value { + p := v.(*bgp.As4PathParam) + if p.Type == bgp.BGP_ASPATH_ATTR_TYPE_SEQ || p.Type == bgp.BGP_ASPATH_ATTR_TYPE_SET { + newAsParams = append(newAsParams, p) + } + } + path.setPathAttr(bgp.NewPathAttributeAsPath(newAsParams)) +} + func (path *Path) ReplaceAS(localAS, peerAS uint32) *Path { original := path.GetAsPath() if original == nil { diff --git a/table/path_test.go b/table/path_test.go index f2b77bc5..768b76bf 100644 --- a/table/path_test.go +++ b/table/path_test.go @@ -116,7 +116,7 @@ func TestPathPrependAsnToExistingSeqAttr(t *testing.T) { peer := PathCreatePeer() p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false) - p.PrependAsn(65000, 1) + p.PrependAsn(65000, 1, false) assert.Equal([]uint32{65000, 65001, 65002, 65003, 65004, 65005, 0, 0, 0}, p.GetAsSeqList()) } @@ -138,7 +138,7 @@ func TestPathPrependAsnToNewAsPathAttr(t *testing.T) { p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false) asn := uint32(65000) - p.PrependAsn(asn, 1) + p.PrependAsn(asn, 1, false) assert.Equal([]uint32{asn}, p.GetAsSeqList()) } @@ -166,7 +166,7 @@ func TestPathPrependAsnToNewAsPathSeq(t *testing.T) { p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false) asn := uint32(65000) - p.PrependAsn(asn, 1) + p.PrependAsn(asn, 1, false) assert.Equal([]uint32{asn, 0, 0, 0}, p.GetAsSeqList()) } @@ -195,7 +195,7 @@ func TestPathPrependAsnToEmptyAsPathAttr(t *testing.T) { p := NewPath(peer[0], update.NLRI[0], false, update.PathAttributes, time.Now(), false) asn := uint32(65000) - p.PrependAsn(asn, 1) + p.PrependAsn(asn, 1, false) assert.Equal([]uint32{asn, 0, 0, 0}, p.GetAsSeqList()) } @@ -233,7 +233,7 @@ func TestPathPrependAsnToFullPathAttr(t *testing.T) { for _, v := range asns { expected = append(expected, uint32(v)) } - p.PrependAsn(65000, 2) + p.PrependAsn(65000, 2, false) assert.Equal(append(expected, []uint32{0, 0, 0}...), p.GetAsSeqList()) } diff --git a/table/policy.go b/table/policy.go index 0d112bba..fe153cf4 100644 --- a/table/policy.go +++ b/table/policy.go @@ -2260,7 +2260,7 @@ func (a *AsPathPrependAction) Type() ActionType { return ACTION_AS_PATH_PREPEND } -func (a *AsPathPrependAction) Apply(path *Path, _ *PolicyOptions) *Path { +func (a *AsPathPrependAction) Apply(path *Path, option *PolicyOptions) *Path { var asn uint32 if a.useLeftMost { aspath := path.GetAsSeqList() @@ -2283,7 +2283,8 @@ func (a *AsPathPrependAction) Apply(path *Path, _ *PolicyOptions) *Path { asn = a.asn } - path.PrependAsn(asn, a.repeat) + confed := option != nil && option.Info.Confederation + path.PrependAsn(asn, a.repeat, confed) return path } |