github.com/osrg/gobgp/v3@v3.30.0/internal/pkg/table/destination_test.go (about) 1 // Copyright (C) 2014 Nippon Telegraph and Telephone Corporation. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package table 17 18 import ( 19 //"fmt" 20 21 "net" 22 "testing" 23 "time" 24 25 "github.com/osrg/gobgp/v3/pkg/packet/bgp" 26 27 "github.com/stretchr/testify/assert" 28 ) 29 30 func TestDestinationNewIPv4(t *testing.T) { 31 peerD := DestCreatePeer() 32 pathD := DestCreatePath(peerD) 33 ipv4d := NewDestination(pathD[0].GetNlri(), 0) 34 assert.NotNil(t, ipv4d) 35 } 36 func TestDestinationNewIPv6(t *testing.T) { 37 peerD := DestCreatePeer() 38 pathD := DestCreatePath(peerD) 39 ipv6d := NewDestination(pathD[0].GetNlri(), 0) 40 assert.NotNil(t, ipv6d) 41 } 42 43 func TestDestinationSetRouteFamily(t *testing.T) { 44 dd := &Destination{} 45 dd.setRouteFamily(bgp.RF_IPv4_UC) 46 rf := dd.Family() 47 assert.Equal(t, rf, bgp.RF_IPv4_UC) 48 } 49 func TestDestinationGetRouteFamily(t *testing.T) { 50 dd := &Destination{} 51 dd.setRouteFamily(bgp.RF_IPv6_UC) 52 rf := dd.Family() 53 assert.Equal(t, rf, bgp.RF_IPv6_UC) 54 } 55 func TestDestinationSetNlri(t *testing.T) { 56 dd := &Destination{} 57 nlri := bgp.NewIPAddrPrefix(24, "13.2.3.1") 58 dd.setNlri(nlri) 59 r_nlri := dd.GetNlri() 60 assert.Equal(t, r_nlri, nlri) 61 } 62 func TestDestinationGetNlri(t *testing.T) { 63 dd := &Destination{} 64 nlri := bgp.NewIPAddrPrefix(24, "10.110.123.1") 65 dd.setNlri(nlri) 66 r_nlri := dd.GetNlri() 67 assert.Equal(t, r_nlri, nlri) 68 } 69 70 func TestCalculate2(t *testing.T) { 71 72 origin := bgp.NewPathAttributeOrigin(0) 73 aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65001})} 74 aspath := bgp.NewPathAttributeAsPath(aspathParam) 75 nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") 76 med := bgp.NewPathAttributeMultiExitDisc(0) 77 pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} 78 nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") 79 80 // peer1 sends normal update message 10.10.0.0/24 81 update1 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) 82 peer1 := &PeerInfo{AS: 1, Address: net.IP{1, 1, 1, 1}} 83 path1 := ProcessMessage(update1, peer1, time.Now())[0] 84 85 d := NewDestination(nlri, 0) 86 d.Calculate(logger, path1) 87 88 // suppose peer2 sends grammaatically correct but semantically flawed update message 89 // which has a withdrawal nlri not advertised before 90 update2 := bgp.NewBGPUpdateMessage([]*bgp.IPAddrPrefix{nlri}, pathAttributes, nil) 91 peer2 := &PeerInfo{AS: 2, Address: net.IP{2, 2, 2, 2}} 92 path2 := ProcessMessage(update2, peer2, time.Now())[0] 93 assert.Equal(t, path2.IsWithdraw, true) 94 95 d.Calculate(logger, path2) 96 97 // we have a path from peer1 here 98 assert.Equal(t, len(d.knownPathList), 1) 99 100 // after that, new update with the same nlri comes from peer2 101 update3 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) 102 path3 := ProcessMessage(update3, peer2, time.Now())[0] 103 assert.Equal(t, path3.IsWithdraw, false) 104 105 d.Calculate(logger, path3) 106 107 // this time, we have paths from peer1 and peer2 108 assert.Equal(t, len(d.knownPathList), 2) 109 110 // now peer3 sends normal update message 10.10.0.0/24 111 peer3 := &PeerInfo{AS: 3, Address: net.IP{3, 3, 3, 3}} 112 update4 := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) 113 path4 := ProcessMessage(update4, peer3, time.Now())[0] 114 115 d.Calculate(logger, path4) 116 117 // we must have paths from peer1, peer2 and peer3 118 assert.Equal(t, len(d.knownPathList), 3) 119 } 120 121 func TestNeighAddrTieBreak(t *testing.T) { 122 nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") 123 124 peer0 := &PeerInfo{AS: 65001, LocalAS: 1, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}} 125 126 p0 := func() *Path { 127 aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001})}) 128 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} 129 return NewPath(peer0, nlri, false, attrs, time.Now(), false) 130 }() 131 132 peer1 := &PeerInfo{AS: 65001, LocalAS: 1, Address: net.IP{3, 3, 3, 3}, ID: net.IP{2, 2, 2, 2}} // same ID as peer0, separate eBGP session 133 134 p1 := func() *Path { 135 aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001})}) 136 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} 137 return NewPath(peer1, nlri, false, attrs, time.Now(), false) 138 }() 139 140 assert.Equal(t, compareByNeighborAddress(p0, p1), p0) 141 } 142 143 func TestMedTieBreaker(t *testing.T) { 144 nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") 145 146 p0 := func() *Path { 147 aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003, 65004})}) 148 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} 149 return NewPath(nil, nlri, false, attrs, time.Now(), false) 150 }() 151 152 p1 := func() *Path { 153 aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003, 65005})}) 154 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)} 155 return NewPath(nil, nlri, false, attrs, time.Now(), false) 156 }() 157 158 // same AS 159 assert.Equal(t, compareByMED(p0, p1), p0) 160 161 p2 := func() *Path { 162 aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003})}) 163 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)} 164 return NewPath(nil, nlri, false, attrs, time.Now(), false) 165 }() 166 167 // different AS 168 assert.Equal(t, compareByMED(p0, p2), (*Path)(nil)) 169 170 p3 := func() *Path { 171 aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint32{65003, 65004}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65003})}) 172 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} 173 return NewPath(nil, nlri, false, attrs, time.Now(), false) 174 }() 175 176 p4 := func() *Path { 177 aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65001, 65002}), bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ, []uint32{65005, 65006})}) 178 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)} 179 return NewPath(nil, nlri, false, attrs, time.Now(), false) 180 }() 181 182 // ignore confed 183 assert.Equal(t, compareByMED(p3, p4), p3) 184 185 p5 := func() *Path { 186 attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeMultiExitDisc(0)} 187 return NewPath(nil, nlri, false, attrs, time.Now(), false) 188 }() 189 190 p6 := func() *Path { 191 attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeMultiExitDisc(10)} 192 return NewPath(nil, nlri, false, attrs, time.Now(), false) 193 }() 194 195 // no aspath 196 assert.Equal(t, compareByMED(p5, p6), p5) 197 } 198 199 func TestTimeTieBreaker(t *testing.T) { 200 origin := bgp.NewPathAttributeOrigin(0) 201 aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65001})} 202 aspath := bgp.NewPathAttributeAsPath(aspathParam) 203 nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") 204 med := bgp.NewPathAttributeMultiExitDisc(0) 205 pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} 206 nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") 207 updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) 208 peer1 := &PeerInfo{AS: 2, LocalAS: 1, Address: net.IP{1, 1, 1, 1}, ID: net.IP{1, 1, 1, 1}} 209 path1 := ProcessMessage(updateMsg, peer1, time.Now())[0] 210 211 peer2 := &PeerInfo{AS: 2, LocalAS: 1, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}} // weaker router-id 212 path2 := ProcessMessage(updateMsg, peer2, time.Now().Add(-1*time.Hour))[0] // older than path1 213 214 d := NewDestination(nlri, 0) 215 d.Calculate(logger, path1) 216 d.Calculate(logger, path2) 217 218 assert.Equal(t, len(d.knownPathList), 2) 219 assert.Equal(t, true, d.GetBestPath("", 0).GetSource().ID.Equal(net.IP{2, 2, 2, 2})) // path from peer2 win 220 221 // this option disables tie breaking by age 222 SelectionOptions.ExternalCompareRouterId = true 223 d = NewDestination(nlri, 0) 224 d.Calculate(logger, path1) 225 d.Calculate(logger, path2) 226 227 assert.Equal(t, len(d.knownPathList), 2) 228 assert.Equal(t, true, d.GetBestPath("", 0).GetSource().ID.Equal(net.IP{1, 1, 1, 1})) // path from peer1 win 229 } 230 231 func DestCreatePeer() []*PeerInfo { 232 peerD1 := &PeerInfo{AS: 65000} 233 peerD2 := &PeerInfo{AS: 65001} 234 peerD3 := &PeerInfo{AS: 65002} 235 peerD := []*PeerInfo{peerD1, peerD2, peerD3} 236 return peerD 237 } 238 239 func DestCreatePath(peerD []*PeerInfo) []*Path { 240 bgpMsgD1 := updateMsgD1() 241 bgpMsgD2 := updateMsgD2() 242 bgpMsgD3 := updateMsgD3() 243 pathD := make([]*Path, 3) 244 for i, msg := range []*bgp.BGPMessage{bgpMsgD1, bgpMsgD2, bgpMsgD3} { 245 updateMsgD := msg.Body.(*bgp.BGPUpdate) 246 nlriList := updateMsgD.NLRI 247 pathAttributes := updateMsgD.PathAttributes 248 nlri_info := nlriList[0] 249 pathD[i] = NewPath(peerD[i], nlri_info, false, pathAttributes, time.Now(), false) 250 } 251 return pathD 252 } 253 254 func updateMsgD1() *bgp.BGPMessage { 255 256 origin := bgp.NewPathAttributeOrigin(0) 257 aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65000})} 258 aspath := bgp.NewPathAttributeAsPath(aspathParam) 259 nexthop := bgp.NewPathAttributeNextHop("192.168.50.1") 260 med := bgp.NewPathAttributeMultiExitDisc(0) 261 262 pathAttributes := []bgp.PathAttributeInterface{ 263 origin, 264 aspath, 265 nexthop, 266 med, 267 } 268 269 nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")} 270 updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 271 UpdatePathAttrs4ByteAs(logger, updateMsg.Body.(*bgp.BGPUpdate)) 272 return updateMsg 273 } 274 275 func updateMsgD2() *bgp.BGPMessage { 276 277 origin := bgp.NewPathAttributeOrigin(0) 278 aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})} 279 aspath := bgp.NewPathAttributeAsPath(aspathParam) 280 nexthop := bgp.NewPathAttributeNextHop("192.168.100.1") 281 med := bgp.NewPathAttributeMultiExitDisc(100) 282 283 pathAttributes := []bgp.PathAttributeInterface{ 284 origin, 285 aspath, 286 nexthop, 287 med, 288 } 289 290 nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "20.20.20.0")} 291 updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 292 UpdatePathAttrs4ByteAs(logger, updateMsg.Body.(*bgp.BGPUpdate)) 293 return updateMsg 294 } 295 func updateMsgD3() *bgp.BGPMessage { 296 origin := bgp.NewPathAttributeOrigin(0) 297 aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})} 298 aspath := bgp.NewPathAttributeAsPath(aspathParam) 299 nexthop := bgp.NewPathAttributeNextHop("192.168.150.1") 300 med := bgp.NewPathAttributeMultiExitDisc(100) 301 302 pathAttributes := []bgp.PathAttributeInterface{ 303 origin, 304 aspath, 305 nexthop, 306 med, 307 } 308 309 nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "30.30.30.0")} 310 w1 := bgp.NewIPAddrPrefix(23, "40.40.40.0") 311 withdrawnRoutes := []*bgp.IPAddrPrefix{w1} 312 updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri) 313 UpdatePathAttrs4ByteAs(logger, updateMsg.Body.(*bgp.BGPUpdate)) 314 return updateMsg 315 } 316 317 func TestMultipath(t *testing.T) { 318 UseMultiplePaths.Enabled = true 319 origin := bgp.NewPathAttributeOrigin(0) 320 aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65000})} 321 aspath := bgp.NewPathAttributeAsPath(aspathParam) 322 nexthop := bgp.NewPathAttributeNextHop("192.168.150.1") 323 med := bgp.NewPathAttributeMultiExitDisc(100) 324 325 pathAttributes := []bgp.PathAttributeInterface{ 326 origin, 327 aspath, 328 nexthop, 329 med, 330 } 331 332 nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")} 333 updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 334 peer1 := &PeerInfo{AS: 1, Address: net.IP{1, 1, 1, 1}, ID: net.IP{1, 1, 1, 1}} 335 path1 := ProcessMessage(updateMsg, peer1, time.Now())[0] 336 peer2 := &PeerInfo{AS: 2, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}} 337 338 med = bgp.NewPathAttributeMultiExitDisc(100) 339 nexthop = bgp.NewPathAttributeNextHop("192.168.150.2") 340 pathAttributes = []bgp.PathAttributeInterface{ 341 origin, 342 aspath, 343 nexthop, 344 med, 345 } 346 updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 347 path2 := ProcessMessage(updateMsg, peer2, time.Now())[0] 348 349 d := NewDestination(nlri[0], 0) 350 d.Calculate(logger, path2) 351 352 best, old, multi := d.Calculate(logger, path1).GetChanges(GLOBAL_RIB_NAME, 0, false) 353 assert.NotNil(t, best) 354 assert.Equal(t, old, path2) 355 assert.Equal(t, len(multi), 2) 356 assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 2) 357 358 path3 := path2.Clone(true) 359 dd := d.Calculate(logger, path3) 360 best, old, multi = dd.GetChanges(GLOBAL_RIB_NAME, 0, false) 361 assert.Nil(t, best) 362 assert.Equal(t, old, path1) 363 assert.Equal(t, len(multi), 1) 364 assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 1) 365 366 peer3 := &PeerInfo{AS: 3, Address: net.IP{3, 3, 3, 3}, ID: net.IP{3, 3, 3, 3}} 367 med = bgp.NewPathAttributeMultiExitDisc(50) 368 nexthop = bgp.NewPathAttributeNextHop("192.168.150.3") 369 pathAttributes = []bgp.PathAttributeInterface{ 370 origin, 371 aspath, 372 nexthop, 373 med, 374 } 375 updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 376 path4 := ProcessMessage(updateMsg, peer3, time.Now())[0] 377 dd = d.Calculate(logger, path4) 378 best, _, multi = dd.GetChanges(GLOBAL_RIB_NAME, 0, false) 379 assert.NotNil(t, best) 380 assert.Equal(t, len(multi), 1) 381 assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 2) 382 383 nexthop = bgp.NewPathAttributeNextHop("192.168.150.2") 384 pathAttributes = []bgp.PathAttributeInterface{ 385 origin, 386 aspath, 387 nexthop, 388 med, 389 } 390 updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 391 path5 := ProcessMessage(updateMsg, peer2, time.Now())[0] 392 best, _, multi = d.Calculate(logger, path5).GetChanges(GLOBAL_RIB_NAME, 0, false) 393 assert.NotNil(t, best) 394 assert.Equal(t, len(multi), 2) 395 assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 3) 396 397 UseMultiplePaths.Enabled = false 398 } 399 400 func TestIdMap(t *testing.T) { 401 d := NewDestination(bgp.NewIPAddrPrefix(24, "10.10.0.101"), 64) 402 for i := 0; ; i++ { 403 if id, err := d.localIdMap.FindandSetZeroBit(); err == nil { 404 assert.Equal(t, uint(i+1), id) 405 } else { 406 assert.Equal(t, i, 63) 407 break 408 } 409 } 410 d.localIdMap.Expand() 411 for i := 0; i < 64; i++ { 412 id, _ := d.localIdMap.FindandSetZeroBit() 413 assert.Equal(t, id, uint(64+i)) 414 } 415 _, err := d.localIdMap.FindandSetZeroBit() 416 assert.NotNil(t, err) 417 } 418 419 func TestGetWithdrawnPath(t *testing.T) { 420 attrs := []bgp.PathAttributeInterface{ 421 bgp.NewPathAttributeOrigin(0), 422 } 423 p1 := NewPath(nil, bgp.NewIPAddrPrefix(24, "13.2.3.0"), false, attrs, time.Now(), false) 424 p2 := NewPath(nil, bgp.NewIPAddrPrefix(24, "13.2.4.0"), false, attrs, time.Now(), false) 425 p3 := NewPath(nil, bgp.NewIPAddrPrefix(24, "13.2.5.0"), false, attrs, time.Now(), false) 426 427 u := &Update{ 428 KnownPathList: []*Path{p2}, 429 OldKnownPathList: []*Path{p1, p2, p3}, 430 } 431 432 l := u.GetWithdrawnPath() 433 assert.Equal(t, len(l), 2) 434 assert.Equal(t, l[0].GetNlri(), p1.GetNlri()) 435 }