summaryrefslogtreecommitdiffhomepage
path: root/table
diff options
context:
space:
mode:
authorSatoshi Fujimoto <satoshi.fujimoto7@gmail.com>2017-09-22 10:29:07 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-11-07 21:53:46 +0900
commit9e584acea92ba17a6792d4724efad0e51c118768 (patch)
tree32456e94ed1de8e57a97cf4a38d88ad43ee86680 /table
parent9d90d038a703f9e37e6fae4c1d035e889161a9c4 (diff)
*: Support BGP Confederations (RFC 5065)
Signed-off-by: Satoshi Fujimoto <satoshi.fujimoto7@gmail.com>
Diffstat (limited to 'table')
-rw-r--r--table/destination.go11
-rw-r--r--table/path.go37
-rw-r--r--table/path_test.go10
-rw-r--r--table/policy.go5
4 files changed, 48 insertions, 15 deletions
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
}