github.com/osrg/gobgp@v2.0.0+incompatible/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 "fmt" 21 "net" 22 "testing" 23 "time" 24 25 "github.com/osrg/gobgp/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(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(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(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(path4) 116 117 // we must have paths from peer1, peer2 and peer3 118 assert.Equal(t, len(d.knownPathList), 3) 119 } 120 121 func TestMedTieBreaker(t *testing.T) { 122 nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") 123 124 p0 := func() *Path { 125 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})}) 126 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} 127 return NewPath(nil, nlri, false, attrs, time.Now(), false) 128 }() 129 130 p1 := func() *Path { 131 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})}) 132 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)} 133 return NewPath(nil, nlri, false, attrs, time.Now(), false) 134 }() 135 136 // same AS 137 assert.Equal(t, compareByMED(p0, p1), p0) 138 139 p2 := func() *Path { 140 aspath := bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{bgp.NewAs4PathParam(bgp.BGP_ASPATH_ATTR_TYPE_SEQ, []uint32{65003})}) 141 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)} 142 return NewPath(nil, nlri, false, attrs, time.Now(), false) 143 }() 144 145 // different AS 146 assert.Equal(t, compareByMED(p0, p2), (*Path)(nil)) 147 148 p3 := func() *Path { 149 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})}) 150 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(0)} 151 return NewPath(nil, nlri, false, attrs, time.Now(), false) 152 }() 153 154 p4 := func() *Path { 155 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})}) 156 attrs := []bgp.PathAttributeInterface{aspath, bgp.NewPathAttributeMultiExitDisc(10)} 157 return NewPath(nil, nlri, false, attrs, time.Now(), false) 158 }() 159 160 // ignore confed 161 assert.Equal(t, compareByMED(p3, p4), p3) 162 163 p5 := func() *Path { 164 attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeMultiExitDisc(0)} 165 return NewPath(nil, nlri, false, attrs, time.Now(), false) 166 }() 167 168 p6 := func() *Path { 169 attrs := []bgp.PathAttributeInterface{bgp.NewPathAttributeMultiExitDisc(10)} 170 return NewPath(nil, nlri, false, attrs, time.Now(), false) 171 }() 172 173 // no aspath 174 assert.Equal(t, compareByMED(p5, p6), p5) 175 } 176 177 func TestTimeTieBreaker(t *testing.T) { 178 origin := bgp.NewPathAttributeOrigin(0) 179 aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65001})} 180 aspath := bgp.NewPathAttributeAsPath(aspathParam) 181 nexthop := bgp.NewPathAttributeNextHop("10.0.0.1") 182 med := bgp.NewPathAttributeMultiExitDisc(0) 183 pathAttributes := []bgp.PathAttributeInterface{origin, aspath, nexthop, med} 184 nlri := bgp.NewIPAddrPrefix(24, "10.10.0.0") 185 updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, []*bgp.IPAddrPrefix{nlri}) 186 peer1 := &PeerInfo{AS: 2, LocalAS: 1, Address: net.IP{1, 1, 1, 1}, ID: net.IP{1, 1, 1, 1}} 187 path1 := ProcessMessage(updateMsg, peer1, time.Now())[0] 188 189 peer2 := &PeerInfo{AS: 2, LocalAS: 1, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}} // weaker router-id 190 path2 := ProcessMessage(updateMsg, peer2, time.Now().Add(-1*time.Hour))[0] // older than path1 191 192 d := NewDestination(nlri, 0) 193 d.Calculate(path1) 194 d.Calculate(path2) 195 196 assert.Equal(t, len(d.knownPathList), 2) 197 assert.Equal(t, true, d.GetBestPath("", 0).GetSource().ID.Equal(net.IP{2, 2, 2, 2})) // path from peer2 win 198 199 // this option disables tie breaking by age 200 SelectionOptions.ExternalCompareRouterId = true 201 d = NewDestination(nlri, 0) 202 d.Calculate(path1) 203 d.Calculate(path2) 204 205 assert.Equal(t, len(d.knownPathList), 2) 206 assert.Equal(t, true, d.GetBestPath("", 0).GetSource().ID.Equal(net.IP{1, 1, 1, 1})) // path from peer1 win 207 } 208 209 func DestCreatePeer() []*PeerInfo { 210 peerD1 := &PeerInfo{AS: 65000} 211 peerD2 := &PeerInfo{AS: 65001} 212 peerD3 := &PeerInfo{AS: 65002} 213 peerD := []*PeerInfo{peerD1, peerD2, peerD3} 214 return peerD 215 } 216 217 func DestCreatePath(peerD []*PeerInfo) []*Path { 218 bgpMsgD1 := updateMsgD1() 219 bgpMsgD2 := updateMsgD2() 220 bgpMsgD3 := updateMsgD3() 221 pathD := make([]*Path, 3) 222 for i, msg := range []*bgp.BGPMessage{bgpMsgD1, bgpMsgD2, bgpMsgD3} { 223 updateMsgD := msg.Body.(*bgp.BGPUpdate) 224 nlriList := updateMsgD.NLRI 225 pathAttributes := updateMsgD.PathAttributes 226 nlri_info := nlriList[0] 227 pathD[i] = NewPath(peerD[i], nlri_info, false, pathAttributes, time.Now(), false) 228 } 229 return pathD 230 } 231 232 func updateMsgD1() *bgp.BGPMessage { 233 234 origin := bgp.NewPathAttributeOrigin(0) 235 aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65000})} 236 aspath := bgp.NewPathAttributeAsPath(aspathParam) 237 nexthop := bgp.NewPathAttributeNextHop("192.168.50.1") 238 med := bgp.NewPathAttributeMultiExitDisc(0) 239 240 pathAttributes := []bgp.PathAttributeInterface{ 241 origin, 242 aspath, 243 nexthop, 244 med, 245 } 246 247 nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")} 248 updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 249 UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) 250 return updateMsg 251 } 252 253 func updateMsgD2() *bgp.BGPMessage { 254 255 origin := bgp.NewPathAttributeOrigin(0) 256 aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})} 257 aspath := bgp.NewPathAttributeAsPath(aspathParam) 258 nexthop := bgp.NewPathAttributeNextHop("192.168.100.1") 259 med := bgp.NewPathAttributeMultiExitDisc(100) 260 261 pathAttributes := []bgp.PathAttributeInterface{ 262 origin, 263 aspath, 264 nexthop, 265 med, 266 } 267 268 nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "20.20.20.0")} 269 updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 270 UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) 271 return updateMsg 272 } 273 func updateMsgD3() *bgp.BGPMessage { 274 origin := bgp.NewPathAttributeOrigin(0) 275 aspathParam := []bgp.AsPathParamInterface{bgp.NewAsPathParam(2, []uint16{65100})} 276 aspath := bgp.NewPathAttributeAsPath(aspathParam) 277 nexthop := bgp.NewPathAttributeNextHop("192.168.150.1") 278 med := bgp.NewPathAttributeMultiExitDisc(100) 279 280 pathAttributes := []bgp.PathAttributeInterface{ 281 origin, 282 aspath, 283 nexthop, 284 med, 285 } 286 287 nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "30.30.30.0")} 288 w1 := bgp.NewIPAddrPrefix(23, "40.40.40.0") 289 withdrawnRoutes := []*bgp.IPAddrPrefix{w1} 290 updateMsg := bgp.NewBGPUpdateMessage(withdrawnRoutes, pathAttributes, nlri) 291 UpdatePathAttrs4ByteAs(updateMsg.Body.(*bgp.BGPUpdate)) 292 return updateMsg 293 } 294 295 func TestRadixkey(t *testing.T) { 296 assert.Equal(t, "000010100000001100100000", CidrToRadixkey("10.3.32.0/24")) 297 assert.Equal(t, "000010100000001100100000", IpToRadixkey(net.ParseIP("10.3.32.0").To4(), 24)) 298 assert.Equal(t, "000010100000001100100000", IpToRadixkey(net.ParseIP("10.3.32.0").To4(), 24)) 299 assert.Equal(t, CidrToRadixkey("::ffff:0.0.0.0/96")+"000010100000001100100000", CidrToRadixkey("::ffff:10.3.32.0/120")) 300 } 301 302 func TestIpToRadixkey(t *testing.T) { 303 for i := byte(0); i < 255; i += 3 { 304 for y := byte(1); y < 128; y *= 2 { 305 ip := net.IPv4(i, i+2, i+3, i-y) 306 for n := uint8(16); n <= 32; n += 2 { 307 exp := CidrToRadixkey(fmt.Sprintf("%v/%d", ip.To4(), n)) 308 got := IpToRadixkey(ip.To4(), n) 309 if exp != got { 310 t.Fatalf(`exp %v; got %v`, exp, got) 311 } 312 } 313 for n := uint8(116); n <= 128; n += 2 { 314 exp := CidrToRadixkey(fmt.Sprintf("::ffff:%v/%d", ip.To16(), n)) 315 got := IpToRadixkey(ip.To16(), n) 316 if exp != got { 317 t.Fatalf(`exp %v; got %v`, exp, got) 318 } 319 } 320 } 321 } 322 } 323 324 func TestMultipath(t *testing.T) { 325 UseMultiplePaths.Enabled = true 326 origin := bgp.NewPathAttributeOrigin(0) 327 aspathParam := []bgp.AsPathParamInterface{bgp.NewAs4PathParam(2, []uint32{65000})} 328 aspath := bgp.NewPathAttributeAsPath(aspathParam) 329 nexthop := bgp.NewPathAttributeNextHop("192.168.150.1") 330 med := bgp.NewPathAttributeMultiExitDisc(100) 331 332 pathAttributes := []bgp.PathAttributeInterface{ 333 origin, 334 aspath, 335 nexthop, 336 med, 337 } 338 339 nlri := []*bgp.IPAddrPrefix{bgp.NewIPAddrPrefix(24, "10.10.10.0")} 340 updateMsg := bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 341 peer1 := &PeerInfo{AS: 1, Address: net.IP{1, 1, 1, 1}, ID: net.IP{1, 1, 1, 1}} 342 path1 := ProcessMessage(updateMsg, peer1, time.Now())[0] 343 peer2 := &PeerInfo{AS: 2, Address: net.IP{2, 2, 2, 2}, ID: net.IP{2, 2, 2, 2}} 344 345 med = bgp.NewPathAttributeMultiExitDisc(100) 346 nexthop = bgp.NewPathAttributeNextHop("192.168.150.2") 347 pathAttributes = []bgp.PathAttributeInterface{ 348 origin, 349 aspath, 350 nexthop, 351 med, 352 } 353 updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 354 path2 := ProcessMessage(updateMsg, peer2, time.Now())[0] 355 356 d := NewDestination(nlri[0], 0) 357 d.Calculate(path2) 358 359 best, old, multi := d.Calculate(path1).GetChanges(GLOBAL_RIB_NAME, 0, false) 360 assert.NotNil(t, best) 361 assert.Equal(t, old, path2) 362 assert.Equal(t, len(multi), 2) 363 assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 2) 364 365 path3 := path2.Clone(true) 366 dd := d.Calculate(path3) 367 best, old, multi = dd.GetChanges(GLOBAL_RIB_NAME, 0, false) 368 assert.Nil(t, best) 369 assert.Equal(t, old, path1) 370 assert.Equal(t, len(multi), 1) 371 assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 1) 372 373 peer3 := &PeerInfo{AS: 3, Address: net.IP{3, 3, 3, 3}, ID: net.IP{3, 3, 3, 3}} 374 med = bgp.NewPathAttributeMultiExitDisc(50) 375 nexthop = bgp.NewPathAttributeNextHop("192.168.150.3") 376 pathAttributes = []bgp.PathAttributeInterface{ 377 origin, 378 aspath, 379 nexthop, 380 med, 381 } 382 updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 383 path4 := ProcessMessage(updateMsg, peer3, time.Now())[0] 384 dd = d.Calculate(path4) 385 best, _, multi = dd.GetChanges(GLOBAL_RIB_NAME, 0, false) 386 assert.NotNil(t, best) 387 assert.Equal(t, len(multi), 1) 388 assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 2) 389 390 nexthop = bgp.NewPathAttributeNextHop("192.168.150.2") 391 pathAttributes = []bgp.PathAttributeInterface{ 392 origin, 393 aspath, 394 nexthop, 395 med, 396 } 397 updateMsg = bgp.NewBGPUpdateMessage(nil, pathAttributes, nlri) 398 path5 := ProcessMessage(updateMsg, peer2, time.Now())[0] 399 best, _, multi = d.Calculate(path5).GetChanges(GLOBAL_RIB_NAME, 0, false) 400 assert.NotNil(t, best) 401 assert.Equal(t, len(multi), 2) 402 assert.Equal(t, len(d.GetKnownPathList(GLOBAL_RIB_NAME, 0)), 3) 403 404 UseMultiplePaths.Enabled = false 405 } 406 407 func TestIdMap(t *testing.T) { 408 d := NewDestination(bgp.NewIPAddrPrefix(24, "10.10.0.101"), 64) 409 for i := 0; ; i++ { 410 if id, err := d.localIdMap.FindandSetZeroBit(); err == nil { 411 assert.Equal(t, uint(i+1), id) 412 } else { 413 assert.Equal(t, i, 63) 414 break 415 } 416 } 417 d.localIdMap.Expand() 418 for i := 0; i < 64; i++ { 419 id, _ := d.localIdMap.FindandSetZeroBit() 420 assert.Equal(t, id, uint(64+i)) 421 } 422 _, err := d.localIdMap.FindandSetZeroBit() 423 assert.NotNil(t, err) 424 } 425 426 func TestGetWithdrawnPath(t *testing.T) { 427 attrs := []bgp.PathAttributeInterface{ 428 bgp.NewPathAttributeOrigin(0), 429 } 430 p1 := NewPath(nil, bgp.NewIPAddrPrefix(24, "13.2.3.0"), false, attrs, time.Now(), false) 431 p2 := NewPath(nil, bgp.NewIPAddrPrefix(24, "13.2.4.0"), false, attrs, time.Now(), false) 432 p3 := NewPath(nil, bgp.NewIPAddrPrefix(24, "13.2.5.0"), false, attrs, time.Now(), false) 433 434 u := &Update{ 435 KnownPathList: []*Path{p2}, 436 OldKnownPathList: []*Path{p1, p2, p3}, 437 } 438 439 l := u.GetWithdrawnPath() 440 assert.Equal(t, len(l), 2) 441 assert.Equal(t, l[0].GetNlri(), p1.GetNlri()) 442 }