github.com/osrg/gobgp@v2.0.0+incompatible/internal/pkg/table/path.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 "bytes" 20 "encoding/json" 21 "fmt" 22 "math" 23 "net" 24 "sort" 25 "time" 26 27 "github.com/osrg/gobgp/internal/pkg/config" 28 "github.com/osrg/gobgp/pkg/packet/bgp" 29 30 log "github.com/sirupsen/logrus" 31 ) 32 33 const ( 34 DEFAULT_LOCAL_PREF = 100 35 ) 36 37 type Bitmap struct { 38 bitmap []uint64 39 } 40 41 func (b *Bitmap) Flag(i uint) { 42 b.bitmap[i/64] |= 1 << uint(i%64) 43 } 44 45 func (b *Bitmap) Unflag(i uint) { 46 b.bitmap[i/64] &^= 1 << uint(i%64) 47 } 48 49 func (b *Bitmap) GetFlag(i uint) bool { 50 return b.bitmap[i/64]&(1<<uint(i%64)) > 0 51 } 52 53 func (b *Bitmap) FindandSetZeroBit() (uint, error) { 54 for i := 0; i < len(b.bitmap); i++ { 55 if b.bitmap[i] == math.MaxUint64 { 56 continue 57 } 58 // replace this with TrailingZero64() when gobgp drops go 1.8 support. 59 for j := 0; j < 64; j++ { 60 v := ^b.bitmap[i] 61 if v&(1<<uint64(j)) > 0 { 62 r := i*64 + j 63 b.Flag(uint(r)) 64 return uint(r), nil 65 } 66 } 67 } 68 return 0, fmt.Errorf("no space") 69 } 70 71 func (b *Bitmap) Expand() { 72 old := b.bitmap 73 new := make([]uint64, len(old)+1) 74 for i := 0; i < len(old); i++ { 75 new[i] = old[i] 76 } 77 b.bitmap = new 78 } 79 80 func NewBitmap(size int) *Bitmap { 81 b := &Bitmap{} 82 if size != 0 { 83 b.bitmap = make([]uint64, (size+64-1)/64) 84 } 85 return b 86 } 87 88 type originInfo struct { 89 nlri bgp.AddrPrefixInterface 90 source *PeerInfo 91 timestamp int64 92 validation *Validation 93 noImplicitWithdraw bool 94 isFromExternal bool 95 eor bool 96 stale bool 97 } 98 99 type RpkiValidationReasonType string 100 101 const ( 102 RPKI_VALIDATION_REASON_TYPE_NONE RpkiValidationReasonType = "none" 103 RPKI_VALIDATION_REASON_TYPE_AS RpkiValidationReasonType = "as" 104 RPKI_VALIDATION_REASON_TYPE_LENGTH RpkiValidationReasonType = "length" 105 ) 106 107 var RpkiValidationReasonTypeToIntMap = map[RpkiValidationReasonType]int{ 108 RPKI_VALIDATION_REASON_TYPE_NONE: 0, 109 RPKI_VALIDATION_REASON_TYPE_AS: 1, 110 RPKI_VALIDATION_REASON_TYPE_LENGTH: 2, 111 } 112 113 func (v RpkiValidationReasonType) ToInt() int { 114 i, ok := RpkiValidationReasonTypeToIntMap[v] 115 if !ok { 116 return -1 117 } 118 return i 119 } 120 121 var IntToRpkiValidationReasonTypeMap = map[int]RpkiValidationReasonType{ 122 0: RPKI_VALIDATION_REASON_TYPE_NONE, 123 1: RPKI_VALIDATION_REASON_TYPE_AS, 124 2: RPKI_VALIDATION_REASON_TYPE_LENGTH, 125 } 126 127 type Validation struct { 128 Status config.RpkiValidationResultType 129 Reason RpkiValidationReasonType 130 Matched []*ROA 131 UnmatchedAs []*ROA 132 UnmatchedLength []*ROA 133 } 134 135 type Path struct { 136 info *originInfo 137 parent *Path 138 pathAttrs []bgp.PathAttributeInterface 139 dels []bgp.BGPAttrType 140 attrsHash uint32 141 aslooped bool 142 reason BestPathReason 143 144 // For BGP Nexthop Tracking, this field shows if nexthop is invalidated by IGP. 145 IsNexthopInvalid bool 146 IsWithdraw bool 147 } 148 149 var localSource = &PeerInfo{} 150 151 func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pattrs []bgp.PathAttributeInterface, timestamp time.Time, noImplicitWithdraw bool) *Path { 152 if source == nil { 153 source = localSource 154 } 155 if !isWithdraw && pattrs == nil { 156 log.WithFields(log.Fields{ 157 "Topic": "Table", 158 "Key": nlri.String(), 159 }).Error("Need to provide path attributes for non-withdrawn path.") 160 return nil 161 } 162 163 return &Path{ 164 info: &originInfo{ 165 nlri: nlri, 166 source: source, 167 timestamp: timestamp.Unix(), 168 noImplicitWithdraw: noImplicitWithdraw, 169 }, 170 IsWithdraw: isWithdraw, 171 pathAttrs: pattrs, 172 } 173 } 174 175 func NewEOR(family bgp.RouteFamily) *Path { 176 afi, safi := bgp.RouteFamilyToAfiSafi(family) 177 nlri, _ := bgp.NewPrefixFromRouteFamily(afi, safi) 178 return &Path{ 179 info: &originInfo{ 180 nlri: nlri, 181 eor: true, 182 }, 183 } 184 } 185 186 func (path *Path) IsEOR() bool { 187 if path.info != nil && path.info.eor { 188 return true 189 } 190 return false 191 } 192 193 func cloneAsPath(asAttr *bgp.PathAttributeAsPath) *bgp.PathAttributeAsPath { 194 newASparams := make([]bgp.AsPathParamInterface, len(asAttr.Value)) 195 for i, param := range asAttr.Value { 196 asList := param.GetAS() 197 as := make([]uint32, len(asList)) 198 copy(as, asList) 199 newASparams[i] = bgp.NewAs4PathParam(param.GetType(), as) 200 } 201 return bgp.NewPathAttributeAsPath(newASparams) 202 } 203 204 func UpdatePathAttrs(global *config.Global, peer *config.Neighbor, info *PeerInfo, original *Path) *Path { 205 if peer.RouteServer.Config.RouteServerClient { 206 return original 207 } 208 path := original.Clone(original.IsWithdraw) 209 210 for _, a := range path.GetPathAttrs() { 211 if _, y := bgp.PathAttrFlags[a.GetType()]; !y { 212 if a.GetFlags()&bgp.BGP_ATTR_FLAG_TRANSITIVE == 0 { 213 path.delPathAttr(a.GetType()) 214 } 215 } else { 216 switch a.GetType() { 217 case bgp.BGP_ATTR_TYPE_CLUSTER_LIST, bgp.BGP_ATTR_TYPE_ORIGINATOR_ID: 218 if !(peer.State.PeerType == config.PEER_TYPE_INTERNAL && peer.RouteReflector.Config.RouteReflectorClient) { 219 // send these attributes to only rr clients 220 path.delPathAttr(a.GetType()) 221 } 222 } 223 } 224 } 225 226 localAddress := info.LocalAddress 227 nexthop := path.GetNexthop() 228 if peer.State.PeerType == config.PEER_TYPE_EXTERNAL { 229 // NEXTHOP handling 230 if !path.IsLocal() || nexthop.IsUnspecified() { 231 path.SetNexthop(localAddress) 232 } 233 234 // remove-private-as handling 235 path.RemovePrivateAS(peer.Config.LocalAs, peer.State.RemovePrivateAs) 236 237 // AS_PATH handling 238 confed := peer.IsConfederationMember(global) 239 path.PrependAsn(peer.Config.LocalAs, 1, confed) 240 if !confed { 241 path.removeConfedAs() 242 } 243 244 // MED Handling 245 if med := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC); med != nil && !path.IsLocal() { 246 path.delPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC) 247 } 248 249 } else if peer.State.PeerType == config.PEER_TYPE_INTERNAL { 250 // NEXTHOP handling for iBGP 251 // if the path generated locally set local address as nexthop. 252 // if not, don't modify it. 253 // TODO: NEXT-HOP-SELF support 254 if path.IsLocal() && nexthop.IsUnspecified() { 255 path.SetNexthop(localAddress) 256 } 257 258 // AS_PATH handling for iBGP 259 // if the path has AS_PATH path attribute, don't modify it. 260 // if not, attach *empty* AS_PATH path attribute. 261 if nh := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH); nh == nil { 262 path.PrependAsn(0, 0, false) 263 } 264 265 // For iBGP peers we are required to send local-pref attribute 266 // for connected or local prefixes. 267 // We set default local-pref 100. 268 if pref := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF); pref == nil { 269 path.setPathAttr(bgp.NewPathAttributeLocalPref(DEFAULT_LOCAL_PREF)) 270 } 271 272 // RFC4456: BGP Route Reflection 273 // 8. Avoiding Routing Information Loops 274 info := path.GetSource() 275 if peer.RouteReflector.Config.RouteReflectorClient { 276 // This attribute will carry the BGP Identifier of the originator of the route in the local AS. 277 // A BGP speaker SHOULD NOT create an ORIGINATOR_ID attribute if one already exists. 278 // 279 // RFC4684 3.2 Intra-AS VPN Route Distribution 280 // When advertising RT membership NLRI to a route-reflector client, 281 // the Originator attribute shall be set to the router-id of the 282 // advertiser, and the Next-hop attribute shall be set of the local 283 // address for that session. 284 if path.GetRouteFamily() == bgp.RF_RTC_UC { 285 path.SetNexthop(localAddress) 286 path.setPathAttr(bgp.NewPathAttributeOriginatorId(info.LocalID.String())) 287 } else if path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGINATOR_ID) == nil { 288 if path.IsLocal() { 289 path.setPathAttr(bgp.NewPathAttributeOriginatorId(global.Config.RouterId)) 290 } else { 291 path.setPathAttr(bgp.NewPathAttributeOriginatorId(info.ID.String())) 292 } 293 } 294 // When an RR reflects a route, it MUST prepend the local CLUSTER_ID to the CLUSTER_LIST. 295 // If the CLUSTER_LIST is empty, it MUST create a new one. 296 clusterID := string(peer.RouteReflector.State.RouteReflectorClusterId) 297 if p := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); p == nil { 298 path.setPathAttr(bgp.NewPathAttributeClusterList([]string{clusterID})) 299 } else { 300 clusterList := p.(*bgp.PathAttributeClusterList) 301 newClusterList := make([]string, 0, len(clusterList.Value)) 302 for _, ip := range clusterList.Value { 303 newClusterList = append(newClusterList, ip.String()) 304 } 305 path.setPathAttr(bgp.NewPathAttributeClusterList(append([]string{clusterID}, newClusterList...))) 306 } 307 } 308 309 } else { 310 log.WithFields(log.Fields{ 311 "Topic": "Peer", 312 "Key": peer.State.NeighborAddress, 313 }).Warnf("invalid peer type: %v", peer.State.PeerType) 314 } 315 return path 316 } 317 318 func (path *Path) GetTimestamp() time.Time { 319 return time.Unix(path.OriginInfo().timestamp, 0) 320 } 321 322 func (path *Path) setTimestamp(t time.Time) { 323 path.OriginInfo().timestamp = t.Unix() 324 } 325 326 func (path *Path) IsLocal() bool { 327 return path.GetSource().Address == nil 328 } 329 330 func (path *Path) IsIBGP() bool { 331 as := path.GetSource().AS 332 return (as == path.GetSource().LocalAS) && as != 0 333 } 334 335 // create new PathAttributes 336 func (path *Path) Clone(isWithdraw bool) *Path { 337 return &Path{ 338 parent: path, 339 IsWithdraw: isWithdraw, 340 IsNexthopInvalid: path.IsNexthopInvalid, 341 attrsHash: path.attrsHash, 342 } 343 } 344 345 func (path *Path) root() *Path { 346 p := path 347 for p.parent != nil { 348 p = p.parent 349 } 350 return p 351 } 352 353 func (path *Path) OriginInfo() *originInfo { 354 return path.root().info 355 } 356 357 func (path *Path) NoImplicitWithdraw() bool { 358 return path.OriginInfo().noImplicitWithdraw 359 } 360 361 func (path *Path) Validation() *Validation { 362 return path.OriginInfo().validation 363 } 364 365 func (path *Path) ValidationStatus() config.RpkiValidationResultType { 366 if v := path.OriginInfo().validation; v != nil { 367 return v.Status 368 } else { 369 return config.RPKI_VALIDATION_RESULT_TYPE_NONE 370 } 371 } 372 373 func (path *Path) SetValidation(v *Validation) { 374 path.OriginInfo().validation = v 375 } 376 377 func (path *Path) IsFromExternal() bool { 378 return path.OriginInfo().isFromExternal 379 } 380 381 func (path *Path) SetIsFromExternal(y bool) { 382 path.OriginInfo().isFromExternal = y 383 } 384 385 func (path *Path) GetRouteFamily() bgp.RouteFamily { 386 return bgp.AfiSafiToRouteFamily(path.OriginInfo().nlri.AFI(), path.OriginInfo().nlri.SAFI()) 387 } 388 389 func (path *Path) GetSource() *PeerInfo { 390 return path.OriginInfo().source 391 } 392 393 func (path *Path) MarkStale(s bool) { 394 path.OriginInfo().stale = s 395 } 396 397 func (path *Path) IsStale() bool { 398 return path.OriginInfo().stale 399 } 400 401 func (path *Path) IsAsLooped() bool { 402 return path.aslooped 403 } 404 405 func (path *Path) SetAsLooped(y bool) { 406 path.aslooped = y 407 } 408 409 func (path *Path) IsLLGRStale() bool { 410 for _, c := range path.GetCommunities() { 411 if c == uint32(bgp.COMMUNITY_LLGR_STALE) { 412 return true 413 } 414 } 415 return false 416 } 417 418 func (path *Path) GetSourceAs() uint32 { 419 attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH) 420 if attr != nil { 421 asPathParam := attr.(*bgp.PathAttributeAsPath).Value 422 if len(asPathParam) == 0 { 423 return 0 424 } 425 asList := asPathParam[len(asPathParam)-1].GetAS() 426 if len(asList) == 0 { 427 return 0 428 } 429 return asList[len(asList)-1] 430 } 431 return 0 432 } 433 434 func (path *Path) GetNexthop() net.IP { 435 attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) 436 if attr != nil { 437 return attr.(*bgp.PathAttributeNextHop).Value 438 } 439 attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) 440 if attr != nil { 441 return attr.(*bgp.PathAttributeMpReachNLRI).Nexthop 442 } 443 return net.IP{} 444 } 445 446 func (path *Path) SetNexthop(nexthop net.IP) { 447 if path.GetRouteFamily() == bgp.RF_IPv4_UC && nexthop.To4() == nil { 448 path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) 449 mpreach := bgp.NewPathAttributeMpReachNLRI(nexthop.String(), []bgp.AddrPrefixInterface{path.GetNlri()}) 450 path.setPathAttr(mpreach) 451 return 452 } 453 attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) 454 if attr != nil { 455 path.setPathAttr(bgp.NewPathAttributeNextHop(nexthop.String())) 456 } 457 attr = path.getPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) 458 if attr != nil { 459 oldNlri := attr.(*bgp.PathAttributeMpReachNLRI) 460 path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nexthop.String(), oldNlri.Value)) 461 } 462 } 463 464 func (path *Path) GetNlri() bgp.AddrPrefixInterface { 465 return path.OriginInfo().nlri 466 } 467 468 type PathAttrs []bgp.PathAttributeInterface 469 470 func (a PathAttrs) Len() int { 471 return len(a) 472 } 473 474 func (a PathAttrs) Swap(i, j int) { 475 a[i], a[j] = a[j], a[i] 476 } 477 478 func (a PathAttrs) Less(i, j int) bool { 479 return a[i].GetType() < a[j].GetType() 480 } 481 482 func (path *Path) GetPathAttrs() []bgp.PathAttributeInterface { 483 deleted := NewBitmap(math.MaxUint8) 484 modified := make(map[uint]bgp.PathAttributeInterface) 485 p := path 486 for { 487 for _, t := range p.dels { 488 deleted.Flag(uint(t)) 489 } 490 if p.parent == nil { 491 list := PathAttrs(make([]bgp.PathAttributeInterface, 0, len(p.pathAttrs))) 492 // we assume that the original pathAttrs are 493 // in order, that is, other bgp speakers send 494 // attributes in order. 495 for _, a := range p.pathAttrs { 496 typ := uint(a.GetType()) 497 if m, ok := modified[typ]; ok { 498 list = append(list, m) 499 delete(modified, typ) 500 } else if !deleted.GetFlag(typ) { 501 list = append(list, a) 502 } 503 } 504 if len(modified) > 0 { 505 // Huh, some attributes were newly 506 // added. So we need to sort... 507 for _, m := range modified { 508 list = append(list, m) 509 } 510 sort.Sort(list) 511 } 512 return list 513 } else { 514 for _, a := range p.pathAttrs { 515 typ := uint(a.GetType()) 516 if _, ok := modified[typ]; !deleted.GetFlag(typ) && !ok { 517 modified[typ] = a 518 } 519 } 520 } 521 p = p.parent 522 } 523 } 524 525 func (path *Path) getPathAttr(typ bgp.BGPAttrType) bgp.PathAttributeInterface { 526 p := path 527 for { 528 for _, t := range p.dels { 529 if t == typ { 530 return nil 531 } 532 } 533 for _, a := range p.pathAttrs { 534 if a.GetType() == typ { 535 return a 536 } 537 } 538 if p.parent == nil { 539 return nil 540 } 541 p = p.parent 542 } 543 } 544 545 func (path *Path) setPathAttr(a bgp.PathAttributeInterface) { 546 if len(path.pathAttrs) == 0 { 547 path.pathAttrs = []bgp.PathAttributeInterface{a} 548 } else { 549 for i, b := range path.pathAttrs { 550 if a.GetType() == b.GetType() { 551 path.pathAttrs[i] = a 552 return 553 } 554 } 555 path.pathAttrs = append(path.pathAttrs, a) 556 } 557 } 558 559 func (path *Path) delPathAttr(typ bgp.BGPAttrType) { 560 if len(path.dels) == 0 { 561 path.dels = []bgp.BGPAttrType{typ} 562 } else { 563 path.dels = append(path.dels, typ) 564 } 565 } 566 567 // return Path's string representation 568 func (path *Path) String() string { 569 s := bytes.NewBuffer(make([]byte, 0, 64)) 570 if path.IsEOR() { 571 s.WriteString(fmt.Sprintf("{ %s EOR | src: %s }", path.GetRouteFamily(), path.GetSource())) 572 return s.String() 573 } 574 s.WriteString(fmt.Sprintf("{ %s | ", path.getPrefix())) 575 s.WriteString(fmt.Sprintf("src: %s", path.GetSource())) 576 s.WriteString(fmt.Sprintf(", nh: %s", path.GetNexthop())) 577 if path.IsNexthopInvalid { 578 s.WriteString(" (not reachable)") 579 } 580 if path.IsWithdraw { 581 s.WriteString(", withdraw") 582 } 583 s.WriteString(" }") 584 return s.String() 585 } 586 587 func (path *Path) getPrefix() string { 588 return path.GetNlri().String() 589 } 590 591 func (path *Path) GetAsPath() *bgp.PathAttributeAsPath { 592 attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_AS_PATH) 593 if attr != nil { 594 return attr.(*bgp.PathAttributeAsPath) 595 } 596 return nil 597 } 598 599 // GetAsPathLen returns the number of AS_PATH 600 func (path *Path) GetAsPathLen() int { 601 602 var length int = 0 603 if aspath := path.GetAsPath(); aspath != nil { 604 for _, as := range aspath.Value { 605 length += as.ASLen() 606 } 607 } 608 return length 609 } 610 611 func (path *Path) GetAsString() string { 612 s := bytes.NewBuffer(make([]byte, 0, 64)) 613 if aspath := path.GetAsPath(); aspath != nil { 614 return bgp.AsPathString(aspath) 615 } 616 return s.String() 617 } 618 619 func (path *Path) GetAsList() []uint32 { 620 return path.getAsListOfSpecificType(true, true) 621 622 } 623 624 func (path *Path) GetAsSeqList() []uint32 { 625 return path.getAsListOfSpecificType(true, false) 626 627 } 628 629 func (path *Path) getAsListOfSpecificType(getAsSeq, getAsSet bool) []uint32 { 630 asList := []uint32{} 631 if aspath := path.GetAsPath(); aspath != nil { 632 for _, param := range aspath.Value { 633 segType := param.GetType() 634 if getAsSeq && segType == bgp.BGP_ASPATH_ATTR_TYPE_SEQ { 635 asList = append(asList, param.GetAS()...) 636 continue 637 } 638 if getAsSet && segType == bgp.BGP_ASPATH_ATTR_TYPE_SET { 639 asList = append(asList, param.GetAS()...) 640 } else { 641 asList = append(asList, 0) 642 } 643 } 644 } 645 return asList 646 } 647 648 func (path *Path) GetLabelString() string { 649 return bgp.LabelString(path.GetNlri()) 650 } 651 652 // PrependAsn prepends AS number. 653 // This function updates the AS_PATH attribute as follows. 654 // (If the peer is in the confederation member AS, 655 // replace AS_SEQUENCE in the following sentence with AS_CONFED_SEQUENCE.) 656 // 1) if the first path segment of the AS_PATH is of type 657 // AS_SEQUENCE, the local system prepends the specified AS num as 658 // the last element of the sequence (put it in the left-most 659 // position with respect to the position of octets in the 660 // protocol message) the specified number of times. 661 // If the act of prepending will cause an overflow in the AS_PATH 662 // segment (i.e., more than 255 ASes), 663 // it SHOULD prepend a new segment of type AS_SEQUENCE 664 // and prepend its own AS number to this new segment. 665 // 666 // 2) if the first path segment of the AS_PATH is of other than type 667 // AS_SEQUENCE, the local system prepends a new path segment of type 668 // AS_SEQUENCE to the AS_PATH, including the specified AS number in 669 // that segment. 670 // 671 // 3) if the AS_PATH is empty, the local system creates a path 672 // segment of type AS_SEQUENCE, places the specified AS number 673 // into that segment, and places that segment into the AS_PATH. 674 func (path *Path) PrependAsn(asn uint32, repeat uint8, confed bool) { 675 var segType uint8 676 if confed { 677 segType = bgp.BGP_ASPATH_ATTR_TYPE_CONFED_SEQ 678 } else { 679 segType = bgp.BGP_ASPATH_ATTR_TYPE_SEQ 680 } 681 682 original := path.GetAsPath() 683 684 asns := make([]uint32, repeat) 685 for i := range asns { 686 asns[i] = asn 687 } 688 689 var asPath *bgp.PathAttributeAsPath 690 if original == nil { 691 asPath = bgp.NewPathAttributeAsPath([]bgp.AsPathParamInterface{}) 692 } else { 693 asPath = cloneAsPath(original) 694 } 695 696 if len(asPath.Value) > 0 { 697 param := asPath.Value[0] 698 asList := param.GetAS() 699 if param.GetType() == segType { 700 if int(repeat)+len(asList) > 255 { 701 repeat = uint8(255 - len(asList)) 702 } 703 newAsList := append(asns[:int(repeat)], asList...) 704 asPath.Value[0] = bgp.NewAs4PathParam(segType, newAsList) 705 asns = asns[int(repeat):] 706 } 707 } 708 709 if len(asns) > 0 { 710 p := bgp.NewAs4PathParam(segType, asns) 711 asPath.Value = append([]bgp.AsPathParamInterface{p}, asPath.Value...) 712 } 713 path.setPathAttr(asPath) 714 } 715 716 func isPrivateAS(as uint32) bool { 717 return (64512 <= as && as <= 65534) || (4200000000 <= as && as <= 4294967294) 718 } 719 720 func (path *Path) RemovePrivateAS(localAS uint32, option config.RemovePrivateAsOption) { 721 original := path.GetAsPath() 722 if original == nil { 723 return 724 } 725 switch option { 726 case config.REMOVE_PRIVATE_AS_OPTION_ALL, config.REMOVE_PRIVATE_AS_OPTION_REPLACE: 727 newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) 728 for _, param := range original.Value { 729 asList := param.GetAS() 730 newASParam := make([]uint32, 0, len(asList)) 731 for _, as := range asList { 732 if isPrivateAS(as) { 733 if option == config.REMOVE_PRIVATE_AS_OPTION_REPLACE { 734 newASParam = append(newASParam, localAS) 735 } 736 } else { 737 newASParam = append(newASParam, as) 738 } 739 } 740 if len(newASParam) > 0 { 741 newASParams = append(newASParams, bgp.NewAs4PathParam(param.GetType(), newASParam)) 742 } 743 } 744 path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams)) 745 } 746 } 747 748 func (path *Path) removeConfedAs() { 749 original := path.GetAsPath() 750 if original == nil { 751 return 752 } 753 newAsParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) 754 for _, param := range original.Value { 755 switch param.GetType() { 756 case bgp.BGP_ASPATH_ATTR_TYPE_SEQ, bgp.BGP_ASPATH_ATTR_TYPE_SET: 757 newAsParams = append(newAsParams, param) 758 } 759 } 760 path.setPathAttr(bgp.NewPathAttributeAsPath(newAsParams)) 761 } 762 763 func (path *Path) ReplaceAS(localAS, peerAS uint32) *Path { 764 original := path.GetAsPath() 765 if original == nil { 766 return path 767 } 768 newASParams := make([]bgp.AsPathParamInterface, 0, len(original.Value)) 769 changed := false 770 for _, param := range original.Value { 771 segType := param.GetType() 772 asList := param.GetAS() 773 newASParam := make([]uint32, 0, len(asList)) 774 for _, as := range asList { 775 if as == peerAS { 776 as = localAS 777 changed = true 778 } 779 newASParam = append(newASParam, as) 780 } 781 newASParams = append(newASParams, bgp.NewAs4PathParam(segType, newASParam)) 782 } 783 if changed { 784 path = path.Clone(path.IsWithdraw) 785 path.setPathAttr(bgp.NewPathAttributeAsPath(newASParams)) 786 } 787 return path 788 } 789 790 func (path *Path) GetCommunities() []uint32 { 791 communityList := []uint32{} 792 if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES); attr != nil { 793 communities := attr.(*bgp.PathAttributeCommunities) 794 communityList = append(communityList, communities.Value...) 795 } 796 return communityList 797 } 798 799 // SetCommunities adds or replaces communities with new ones. 800 // If the length of communities is 0 and doReplace is true, it clears communities. 801 func (path *Path) SetCommunities(communities []uint32, doReplace bool) { 802 803 if len(communities) == 0 && doReplace { 804 // clear communities 805 path.delPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES) 806 return 807 } 808 809 newList := make([]uint32, 0) 810 attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES) 811 if attr != nil { 812 c := attr.(*bgp.PathAttributeCommunities) 813 if doReplace { 814 newList = append(newList, communities...) 815 } else { 816 newList = append(newList, c.Value...) 817 newList = append(newList, communities...) 818 } 819 } else { 820 newList = append(newList, communities...) 821 } 822 path.setPathAttr(bgp.NewPathAttributeCommunities(newList)) 823 824 } 825 826 // RemoveCommunities removes specific communities. 827 // If the length of communities is 0, it does nothing. 828 // If all communities are removed, it removes Communities path attribute itself. 829 func (path *Path) RemoveCommunities(communities []uint32) int { 830 831 if len(communities) == 0 { 832 // do nothing 833 return 0 834 } 835 836 find := func(val uint32) bool { 837 for _, com := range communities { 838 if com == val { 839 return true 840 } 841 } 842 return false 843 } 844 845 count := 0 846 attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES) 847 if attr != nil { 848 newList := make([]uint32, 0) 849 c := attr.(*bgp.PathAttributeCommunities) 850 851 for _, value := range c.Value { 852 if find(value) { 853 count += 1 854 } else { 855 newList = append(newList, value) 856 } 857 } 858 859 if len(newList) != 0 { 860 path.setPathAttr(bgp.NewPathAttributeCommunities(newList)) 861 } else { 862 path.delPathAttr(bgp.BGP_ATTR_TYPE_COMMUNITIES) 863 } 864 } 865 return count 866 } 867 868 func (path *Path) GetExtCommunities() []bgp.ExtendedCommunityInterface { 869 eCommunityList := make([]bgp.ExtendedCommunityInterface, 0) 870 if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES); attr != nil { 871 eCommunities := attr.(*bgp.PathAttributeExtendedCommunities).Value 872 eCommunityList = append(eCommunityList, eCommunities...) 873 } 874 return eCommunityList 875 } 876 877 func (path *Path) SetExtCommunities(exts []bgp.ExtendedCommunityInterface, doReplace bool) { 878 attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES) 879 if attr != nil { 880 l := attr.(*bgp.PathAttributeExtendedCommunities).Value 881 if doReplace { 882 l = exts 883 } else { 884 l = append(l, exts...) 885 } 886 path.setPathAttr(bgp.NewPathAttributeExtendedCommunities(l)) 887 } else { 888 path.setPathAttr(bgp.NewPathAttributeExtendedCommunities(exts)) 889 } 890 } 891 892 func (path *Path) GetLargeCommunities() []*bgp.LargeCommunity { 893 if a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY); a != nil { 894 v := a.(*bgp.PathAttributeLargeCommunities).Values 895 ret := make([]*bgp.LargeCommunity, 0, len(v)) 896 ret = append(ret, v...) 897 return ret 898 } 899 return nil 900 } 901 902 func (path *Path) SetLargeCommunities(cs []*bgp.LargeCommunity, doReplace bool) { 903 a := path.getPathAttr(bgp.BGP_ATTR_TYPE_LARGE_COMMUNITY) 904 if a == nil || doReplace { 905 path.setPathAttr(bgp.NewPathAttributeLargeCommunities(cs)) 906 } else { 907 l := a.(*bgp.PathAttributeLargeCommunities).Values 908 path.setPathAttr(bgp.NewPathAttributeLargeCommunities(append(l, cs...))) 909 } 910 } 911 912 func (path *Path) GetMed() (uint32, error) { 913 attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC) 914 if attr == nil { 915 return 0, fmt.Errorf("no med path attr") 916 } 917 return attr.(*bgp.PathAttributeMultiExitDisc).Value, nil 918 } 919 920 // SetMed replace, add or subtraction med with new ones. 921 func (path *Path) SetMed(med int64, doReplace bool) error { 922 parseMed := func(orgMed uint32, med int64, doReplace bool) (*bgp.PathAttributeMultiExitDisc, error) { 923 if doReplace { 924 return bgp.NewPathAttributeMultiExitDisc(uint32(med)), nil 925 } 926 927 medVal := int64(orgMed) + med 928 if medVal < 0 { 929 return nil, fmt.Errorf("med value invalid. it's underflow threshold: %v", medVal) 930 } else if medVal > int64(math.MaxUint32) { 931 return nil, fmt.Errorf("med value invalid. it's overflow threshold: %v", medVal) 932 } 933 934 return bgp.NewPathAttributeMultiExitDisc(uint32(int64(orgMed) + med)), nil 935 } 936 937 m := uint32(0) 938 if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_MULTI_EXIT_DISC); attr != nil { 939 m = attr.(*bgp.PathAttributeMultiExitDisc).Value 940 } 941 newMed, err := parseMed(m, med, doReplace) 942 if err != nil { 943 return err 944 } 945 path.setPathAttr(newMed) 946 return nil 947 } 948 949 func (path *Path) RemoveLocalPref() { 950 if path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF) != nil { 951 path.delPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF) 952 } 953 } 954 955 func (path *Path) GetOriginatorID() net.IP { 956 if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGINATOR_ID); attr != nil { 957 return attr.(*bgp.PathAttributeOriginatorId).Value 958 } 959 return nil 960 } 961 962 func (path *Path) GetClusterList() []net.IP { 963 if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_CLUSTER_LIST); attr != nil { 964 return attr.(*bgp.PathAttributeClusterList).Value 965 } 966 return nil 967 } 968 969 func (path *Path) GetOrigin() (uint8, error) { 970 if attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_ORIGIN); attr != nil { 971 return attr.(*bgp.PathAttributeOrigin).Value, nil 972 } 973 return 0, fmt.Errorf("no origin path attr") 974 } 975 976 func (path *Path) GetLocalPref() (uint32, error) { 977 lp := uint32(DEFAULT_LOCAL_PREF) 978 attr := path.getPathAttr(bgp.BGP_ATTR_TYPE_LOCAL_PREF) 979 if attr != nil { 980 lp = attr.(*bgp.PathAttributeLocalPref).Value 981 } 982 return lp, nil 983 } 984 985 func (lhs *Path) Equal(rhs *Path) bool { 986 if rhs == nil { 987 return false 988 } 989 990 if !lhs.GetSource().Equal(rhs.GetSource()) { 991 return false 992 } 993 994 pattrs := func(arg []bgp.PathAttributeInterface) []byte { 995 ret := make([]byte, 0) 996 for _, a := range arg { 997 aa, _ := a.Serialize() 998 ret = append(ret, aa...) 999 } 1000 return ret 1001 } 1002 return bytes.Equal(pattrs(lhs.GetPathAttrs()), pattrs(rhs.GetPathAttrs())) 1003 } 1004 1005 func (path *Path) MarshalJSON() ([]byte, error) { 1006 return json.Marshal(struct { 1007 Nlri bgp.AddrPrefixInterface `json:"nlri"` 1008 PathAttrs []bgp.PathAttributeInterface `json:"attrs"` 1009 Age int64 `json:"age"` 1010 Withdrawal bool `json:"withdrawal,omitempty"` 1011 Validation string `json:"validation,omitempty"` 1012 SourceID net.IP `json:"source-id,omitempty"` 1013 NeighborIP net.IP `json:"neighbor-ip,omitempty"` 1014 Stale bool `json:"stale,omitempty"` 1015 UUID string `json:"uuid,omitempty"` 1016 ID uint32 `json:"id,omitempty"` 1017 }{ 1018 Nlri: path.GetNlri(), 1019 PathAttrs: path.GetPathAttrs(), 1020 Age: path.GetTimestamp().Unix(), 1021 Withdrawal: path.IsWithdraw, 1022 Validation: string(path.ValidationStatus()), 1023 SourceID: path.GetSource().ID, 1024 NeighborIP: path.GetSource().Address, 1025 Stale: path.IsStale(), 1026 ID: path.GetNlri().PathIdentifier(), 1027 }) 1028 } 1029 1030 func (lhs *Path) Compare(rhs *Path) int { 1031 if lhs.IsLocal() && !rhs.IsLocal() { 1032 return 1 1033 } else if !lhs.IsLocal() && rhs.IsLocal() { 1034 return -1 1035 } 1036 1037 if !lhs.IsIBGP() && rhs.IsIBGP() { 1038 return 1 1039 } else if lhs.IsIBGP() && !rhs.IsIBGP() { 1040 return -1 1041 } 1042 1043 lp1, _ := lhs.GetLocalPref() 1044 lp2, _ := rhs.GetLocalPref() 1045 if lp1 != lp2 { 1046 return int(lp1 - lp2) 1047 } 1048 1049 l1 := lhs.GetAsPathLen() 1050 l2 := rhs.GetAsPathLen() 1051 if l1 != l2 { 1052 return int(l2 - l1) 1053 } 1054 1055 o1, _ := lhs.GetOrigin() 1056 o2, _ := rhs.GetOrigin() 1057 if o1 != o2 { 1058 return int(o2 - o1) 1059 } 1060 1061 m1, _ := lhs.GetMed() 1062 m2, _ := rhs.GetMed() 1063 return int(m2 - m1) 1064 } 1065 1066 func (v *Vrf) ToGlobalPath(path *Path) error { 1067 nlri := path.GetNlri() 1068 switch rf := path.GetRouteFamily(); rf { 1069 case bgp.RF_IPv4_UC: 1070 n := nlri.(*bgp.IPAddrPrefix) 1071 pathIdentifier := path.GetNlri().PathIdentifier() 1072 path.OriginInfo().nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd) 1073 path.GetNlri().SetPathIdentifier(pathIdentifier) 1074 case bgp.RF_IPv6_UC: 1075 n := nlri.(*bgp.IPv6AddrPrefix) 1076 pathIdentifier := path.GetNlri().PathIdentifier() 1077 path.OriginInfo().nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), v.Rd) 1078 path.GetNlri().SetPathIdentifier(pathIdentifier) 1079 case bgp.RF_EVPN: 1080 n := nlri.(*bgp.EVPNNLRI) 1081 switch n.RouteType { 1082 case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT: 1083 n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute).RD = v.Rd 1084 case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: 1085 n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute).RD = v.Rd 1086 } 1087 default: 1088 return fmt.Errorf("unsupported route family for vrf: %s", rf) 1089 } 1090 path.SetExtCommunities(v.ExportRt, false) 1091 return nil 1092 } 1093 1094 func (p *Path) ToGlobal(vrf *Vrf) *Path { 1095 nlri := p.GetNlri() 1096 nh := p.GetNexthop() 1097 pathId := nlri.PathIdentifier() 1098 switch rf := p.GetRouteFamily(); rf { 1099 case bgp.RF_IPv4_UC: 1100 n := nlri.(*bgp.IPAddrPrefix) 1101 nlri = bgp.NewLabeledVPNIPAddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd) 1102 nlri.SetPathIdentifier(pathId) 1103 case bgp.RF_IPv6_UC: 1104 n := nlri.(*bgp.IPv6AddrPrefix) 1105 nlri = bgp.NewLabeledVPNIPv6AddrPrefix(n.Length, n.Prefix.String(), *bgp.NewMPLSLabelStack(0), vrf.Rd) 1106 nlri.SetPathIdentifier(pathId) 1107 case bgp.RF_EVPN: 1108 n := nlri.(*bgp.EVPNNLRI) 1109 switch n.RouteType { 1110 case bgp.EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT: 1111 old := n.RouteTypeData.(*bgp.EVPNMacIPAdvertisementRoute) 1112 new := &bgp.EVPNMacIPAdvertisementRoute{ 1113 RD: vrf.Rd, 1114 ESI: old.ESI, 1115 ETag: old.ETag, 1116 MacAddressLength: old.MacAddressLength, 1117 MacAddress: old.MacAddress, 1118 IPAddressLength: old.IPAddressLength, 1119 IPAddress: old.IPAddress, 1120 Labels: old.Labels, 1121 } 1122 nlri = bgp.NewEVPNNLRI(n.RouteType, new) 1123 case bgp.EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: 1124 old := n.RouteTypeData.(*bgp.EVPNMulticastEthernetTagRoute) 1125 new := &bgp.EVPNMulticastEthernetTagRoute{ 1126 RD: vrf.Rd, 1127 ETag: old.ETag, 1128 IPAddressLength: old.IPAddressLength, 1129 IPAddress: old.IPAddress, 1130 } 1131 nlri = bgp.NewEVPNNLRI(n.RouteType, new) 1132 } 1133 default: 1134 return p 1135 } 1136 path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.GetTimestamp(), false) 1137 path.SetExtCommunities(vrf.ExportRt, false) 1138 path.delPathAttr(bgp.BGP_ATTR_TYPE_NEXT_HOP) 1139 path.setPathAttr(bgp.NewPathAttributeMpReachNLRI(nh.String(), []bgp.AddrPrefixInterface{nlri})) 1140 path.IsNexthopInvalid = p.IsNexthopInvalid 1141 return path 1142 } 1143 1144 func (p *Path) ToLocal() *Path { 1145 nlri := p.GetNlri() 1146 f := p.GetRouteFamily() 1147 pathId := nlri.PathLocalIdentifier() 1148 switch f { 1149 case bgp.RF_IPv4_VPN: 1150 n := nlri.(*bgp.LabeledVPNIPAddrPrefix) 1151 _, c, _ := net.ParseCIDR(n.IPPrefix()) 1152 ones, _ := c.Mask.Size() 1153 nlri = bgp.NewIPAddrPrefix(uint8(ones), c.IP.String()) 1154 nlri.SetPathLocalIdentifier(pathId) 1155 case bgp.RF_IPv6_VPN: 1156 n := nlri.(*bgp.LabeledVPNIPv6AddrPrefix) 1157 _, c, _ := net.ParseCIDR(n.IPPrefix()) 1158 ones, _ := c.Mask.Size() 1159 nlri = bgp.NewIPv6AddrPrefix(uint8(ones), c.IP.String()) 1160 nlri.SetPathLocalIdentifier(pathId) 1161 default: 1162 return p 1163 } 1164 path := NewPath(p.OriginInfo().source, nlri, p.IsWithdraw, p.GetPathAttrs(), p.GetTimestamp(), false) 1165 path.delPathAttr(bgp.BGP_ATTR_TYPE_EXTENDED_COMMUNITIES) 1166 1167 if f == bgp.RF_IPv4_VPN { 1168 nh := path.GetNexthop() 1169 path.delPathAttr(bgp.BGP_ATTR_TYPE_MP_REACH_NLRI) 1170 path.setPathAttr(bgp.NewPathAttributeNextHop(nh.String())) 1171 } 1172 path.IsNexthopInvalid = p.IsNexthopInvalid 1173 return path 1174 } 1175 1176 func (p *Path) SetHash(v uint32) { 1177 p.attrsHash = v 1178 } 1179 1180 func (p *Path) GetHash() uint32 { 1181 return p.attrsHash 1182 }