github.com/osrg/gobgp/v3@v3.30.0/pkg/packet/mrt/mrt.go (about) 1 // Copyright (C) 2015 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 mrt 17 18 import ( 19 "bytes" 20 "encoding/binary" 21 "errors" 22 "fmt" 23 "math" 24 "net" 25 "time" 26 27 "github.com/osrg/gobgp/v3/pkg/packet/bgp" 28 ) 29 30 const ( 31 MRT_COMMON_HEADER_LEN = 12 32 ) 33 34 type MRTType uint16 35 36 const ( 37 NULL MRTType = 0 // deprecated 38 START MRTType = 1 // deprecated 39 DIE MRTType = 2 // deprecated 40 I_AM_DEAD MRTType = 3 // deprecated 41 PEER_DOWN MRTType = 4 // deprecated 42 BGP MRTType = 5 // deprecated 43 RIP MRTType = 6 // deprecated 44 IDRP MRTType = 7 // deprecated 45 RIPNG MRTType = 8 // deprecated 46 BGP4PLUS MRTType = 9 // deprecated 47 BGP4PLUS01 MRTType = 10 // deprecated 48 OSPFv2 MRTType = 11 49 TABLE_DUMP MRTType = 12 50 TABLE_DUMPv2 MRTType = 13 51 BGP4MP MRTType = 16 52 BGP4MP_ET MRTType = 17 53 ISIS MRTType = 32 54 ISIS_ET MRTType = 33 55 OSPFv3 MRTType = 48 56 OSPFv3_ET MRTType = 49 57 ) 58 59 type MRTSubTyper interface { 60 ToUint16() uint16 61 } 62 63 type MRTSubTypeTableDumpv2 uint16 64 65 const ( 66 PEER_INDEX_TABLE MRTSubTypeTableDumpv2 = 1 67 RIB_IPV4_UNICAST MRTSubTypeTableDumpv2 = 2 68 RIB_IPV4_MULTICAST MRTSubTypeTableDumpv2 = 3 69 RIB_IPV6_UNICAST MRTSubTypeTableDumpv2 = 4 70 RIB_IPV6_MULTICAST MRTSubTypeTableDumpv2 = 5 71 RIB_GENERIC MRTSubTypeTableDumpv2 = 6 72 GEO_PEER_TABLE MRTSubTypeTableDumpv2 = 7 // RFC6397 73 RIB_IPV4_UNICAST_ADDPATH MRTSubTypeTableDumpv2 = 8 // RFC8050 74 RIB_IPV4_MULTICAST_ADDPATH MRTSubTypeTableDumpv2 = 9 // RFC8050 75 RIB_IPV6_UNICAST_ADDPATH MRTSubTypeTableDumpv2 = 10 // RFC8050 76 RIB_IPV6_MULTICAST_ADDPATH MRTSubTypeTableDumpv2 = 11 // RFC8050 77 RIB_GENERIC_ADDPATH MRTSubTypeTableDumpv2 = 12 // RFC8050 78 ) 79 80 func (t MRTSubTypeTableDumpv2) ToUint16() uint16 { 81 return uint16(t) 82 } 83 84 type MRTSubTypeBGP4MP uint16 85 86 const ( 87 STATE_CHANGE MRTSubTypeBGP4MP = 0 88 MESSAGE MRTSubTypeBGP4MP = 1 89 MESSAGE_AS4 MRTSubTypeBGP4MP = 4 90 STATE_CHANGE_AS4 MRTSubTypeBGP4MP = 5 91 MESSAGE_LOCAL MRTSubTypeBGP4MP = 6 92 MESSAGE_AS4_LOCAL MRTSubTypeBGP4MP = 7 93 MESSAGE_ADDPATH MRTSubTypeBGP4MP = 8 // RFC8050 94 MESSAGE_AS4_ADDPATH MRTSubTypeBGP4MP = 9 // RFC8050 95 MESSAGE_LOCAL_ADDPATH MRTSubTypeBGP4MP = 10 // RFC8050 96 MESSAGE_AS4_LOCAL_ADDPATH MRTSubTypeBGP4MP = 11 // RFC8050 97 ) 98 99 func (t MRTSubTypeBGP4MP) ToUint16() uint16 { 100 return uint16(t) 101 } 102 103 type BGPState uint16 104 105 const ( 106 IDLE BGPState = 1 107 CONNECT BGPState = 2 108 ACTIVE BGPState = 3 109 OPENSENT BGPState = 4 110 OPENCONFIRM BGPState = 5 111 ESTABLISHED BGPState = 6 112 ) 113 114 func packValues(values []interface{}) ([]byte, error) { 115 b := new(bytes.Buffer) 116 for _, v := range values { 117 err := binary.Write(b, binary.BigEndian, v) 118 if err != nil { 119 return nil, err 120 } 121 } 122 return b.Bytes(), nil 123 } 124 125 type MRTHeader struct { 126 Timestamp uint32 127 Type MRTType 128 SubType uint16 129 Len uint32 130 } 131 132 func (h *MRTHeader) DecodeFromBytes(data []byte) error { 133 if len(data) < MRT_COMMON_HEADER_LEN { 134 return fmt.Errorf("not all MRTHeader bytes are available. expected: %d, actual: %d", MRT_COMMON_HEADER_LEN, len(data)) 135 } 136 h.Timestamp = binary.BigEndian.Uint32(data[:4]) 137 h.Type = MRTType(binary.BigEndian.Uint16(data[4:6])) 138 h.SubType = binary.BigEndian.Uint16(data[6:8]) 139 h.Len = binary.BigEndian.Uint32(data[8:12]) 140 return nil 141 } 142 143 func (h *MRTHeader) Serialize() ([]byte, error) { 144 return packValues([]interface{}{h.Timestamp, h.Type, h.SubType, h.Len}) 145 } 146 147 func NewMRTHeader(timestamp uint32, t MRTType, subtype MRTSubTyper, l uint32) (*MRTHeader, error) { 148 return &MRTHeader{ 149 Timestamp: timestamp, 150 Type: t, 151 SubType: subtype.ToUint16(), 152 Len: l, 153 }, nil 154 } 155 156 func (h *MRTHeader) GetTime() time.Time { 157 t := int64(h.Timestamp) 158 return time.Unix(t, 0) 159 } 160 161 type MRTMessage struct { 162 Header MRTHeader 163 Body Body 164 } 165 166 func (m *MRTMessage) Serialize() ([]byte, error) { 167 buf, err := m.Body.Serialize() 168 if err != nil { 169 return nil, err 170 } 171 m.Header.Len = uint32(len(buf)) 172 bbuf, err := m.Header.Serialize() 173 if err != nil { 174 return nil, err 175 } 176 return append(bbuf, buf...), nil 177 } 178 179 func NewMRTMessage(timestamp uint32, t MRTType, subtype MRTSubTyper, body Body) (*MRTMessage, error) { 180 header, err := NewMRTHeader(timestamp, t, subtype, 0) 181 if err != nil { 182 return nil, err 183 } 184 return &MRTMessage{ 185 Header: *header, 186 Body: body, 187 }, nil 188 } 189 190 type Body interface { 191 DecodeFromBytes([]byte) error 192 Serialize() ([]byte, error) 193 } 194 195 type Peer struct { 196 Type uint8 197 BgpId net.IP 198 IpAddress net.IP 199 AS uint32 200 } 201 202 var errNotAllPeerBytesAvailable = errors.New("not all Peer bytes are available") 203 204 func (p *Peer) DecodeFromBytes(data []byte) ([]byte, error) { 205 if len(data) < 5 { 206 return nil, errNotAllPeerBytesAvailable 207 } 208 p.Type = uint8(data[0]) 209 p.BgpId = net.IP(data[1:5]) 210 data = data[5:] 211 212 if p.Type&1 > 0 { 213 if len(data) < 16 { 214 return nil, errNotAllPeerBytesAvailable 215 } 216 p.IpAddress = net.IP(data[:16]) 217 data = data[16:] 218 } else { 219 if len(data) < 4 { 220 return nil, errNotAllPeerBytesAvailable 221 } 222 p.IpAddress = net.IP(data[:4]) 223 data = data[4:] 224 } 225 226 if p.Type&(1<<1) > 0 { 227 if len(data) < 4 { 228 return nil, errNotAllPeerBytesAvailable 229 } 230 p.AS = binary.BigEndian.Uint32(data[:4]) 231 data = data[4:] 232 } else { 233 if len(data) < 2 { 234 return nil, errNotAllPeerBytesAvailable 235 } 236 p.AS = uint32(binary.BigEndian.Uint16(data[:2])) 237 data = data[2:] 238 } 239 240 return data, nil 241 } 242 243 func (p *Peer) Serialize() ([]byte, error) { 244 var err error 245 var bbuf []byte 246 buf := make([]byte, 5) 247 buf[0] = uint8(p.Type) 248 copy(buf[1:], p.BgpId.To4()) 249 if p.Type&1 > 0 { 250 buf = append(buf, p.IpAddress.To16()...) 251 } else { 252 buf = append(buf, p.IpAddress.To4()...) 253 } 254 if p.Type&(1<<1) > 0 { 255 bbuf, err = packValues([]interface{}{p.AS}) 256 } else { 257 if p.AS > uint32(math.MaxUint16) { 258 return nil, fmt.Errorf("AS number is beyond 2 octet. %d > %d", p.AS, math.MaxUint16) 259 } 260 bbuf, err = packValues([]interface{}{uint16(p.AS)}) 261 } 262 if err != nil { 263 return nil, err 264 } 265 return append(buf, bbuf...), nil 266 } 267 268 func NewPeer(bgpid string, ipaddr string, asn uint32, isAS4 bool) *Peer { 269 t := 0 270 addr := net.ParseIP(ipaddr).To4() 271 if addr == nil { 272 t |= 1 273 addr = net.ParseIP(ipaddr).To16() 274 } 275 if isAS4 { 276 t |= (1 << 1) 277 } 278 return &Peer{ 279 Type: uint8(t), 280 BgpId: net.ParseIP(bgpid).To4(), 281 IpAddress: addr, 282 AS: asn, 283 } 284 } 285 286 func (p *Peer) String() string { 287 return fmt.Sprintf("PEER ENTRY: ID [%s] Addr [%s] AS [%d]", p.BgpId, p.IpAddress, p.AS) 288 } 289 290 type PeerIndexTable struct { 291 CollectorBgpId net.IP 292 ViewName string 293 Peers []*Peer 294 } 295 296 var errNnotAllPeerIndexBytesAvailable = errors.New("not all PeerIndexTable bytes are available") 297 298 func (t *PeerIndexTable) DecodeFromBytes(data []byte) error { 299 if len(data) < 6 { 300 return errNnotAllPeerIndexBytesAvailable 301 } 302 t.CollectorBgpId = net.IP(data[:4]) 303 viewLen := binary.BigEndian.Uint16(data[4:6]) 304 if len(data) < 6+int(viewLen) { 305 return errNnotAllPeerIndexBytesAvailable 306 } 307 t.ViewName = string(data[6 : 6+viewLen]) 308 309 data = data[6+viewLen:] 310 311 if len(data) < 2 { 312 return errNnotAllPeerIndexBytesAvailable 313 } 314 peerNum := binary.BigEndian.Uint16(data[:2]) 315 data = data[2:] 316 t.Peers = make([]*Peer, 0, peerNum) 317 var err error 318 for i := 0; i < int(peerNum); i++ { 319 p := &Peer{} 320 data, err = p.DecodeFromBytes(data) 321 if err != nil { 322 return err 323 } 324 t.Peers = append(t.Peers, p) 325 } 326 327 return nil 328 } 329 330 func (t *PeerIndexTable) Serialize() ([]byte, error) { 331 buf := make([]byte, 8+len(t.ViewName)) 332 copy(buf, t.CollectorBgpId.To4()) 333 binary.BigEndian.PutUint16(buf[4:], uint16(len(t.ViewName))) 334 copy(buf[6:], t.ViewName) 335 binary.BigEndian.PutUint16(buf[6+len(t.ViewName):], uint16(len(t.Peers))) 336 for _, peer := range t.Peers { 337 bbuf, err := peer.Serialize() 338 if err != nil { 339 return nil, err 340 } 341 buf = append(buf, bbuf...) 342 } 343 return buf, nil 344 } 345 346 func NewPeerIndexTable(bgpid string, viewname string, peers []*Peer) *PeerIndexTable { 347 return &PeerIndexTable{ 348 CollectorBgpId: net.ParseIP(bgpid).To4(), 349 ViewName: viewname, 350 Peers: peers, 351 } 352 } 353 354 func (t *PeerIndexTable) String() string { 355 return fmt.Sprintf("PEER_INDEX_TABLE: CollectorBgpId [%s] ViewName [%s] Peers [%s]", t.CollectorBgpId, t.ViewName, t.Peers) 356 } 357 358 type RibEntry struct { 359 PeerIndex uint16 360 OriginatedTime uint32 361 PathIdentifier uint32 362 PathAttributes []bgp.PathAttributeInterface 363 isAddPath bool 364 } 365 366 var errNotAllRibEntryBytesAvailable = errors.New("not all RibEntry bytes are available") 367 368 func (e *RibEntry) DecodeFromBytes(data []byte, prefix ...bgp.AddrPrefixInterface) ([]byte, error) { 369 if len(data) < 8 { 370 return nil, errNotAllRibEntryBytesAvailable 371 } 372 e.PeerIndex = binary.BigEndian.Uint16(data[:2]) 373 e.OriginatedTime = binary.BigEndian.Uint32(data[2:6]) 374 if e.isAddPath { 375 e.PathIdentifier = binary.BigEndian.Uint32(data[6:10]) 376 data = data[10:] 377 } else { 378 data = data[6:] 379 } 380 totalLen := binary.BigEndian.Uint16(data[:2]) 381 data = data[2:] 382 for attrLen := totalLen; attrLen > 0; { 383 p, err := bgp.GetPathAttribute(data) 384 if err != nil { 385 return nil, err 386 } 387 388 // HACK: keeps compatibility 389 switch len(prefix) { 390 case 0: 391 err = p.DecodeFromBytes(data) 392 case 1: 393 err = p.DecodeFromBytes(data, &bgp.MarshallingOption{ImplicitPrefix: prefix[0]}) 394 default: 395 return nil, fmt.Errorf("only one prefix should be used") 396 } 397 if err != nil { 398 return nil, err 399 } 400 attrLen -= uint16(p.Len()) 401 if len(data) < p.Len() { 402 return nil, errNotAllRibEntryBytesAvailable 403 } 404 data = data[p.Len():] 405 e.PathAttributes = append(e.PathAttributes, p) 406 } 407 return data, nil 408 } 409 410 func (e *RibEntry) Serialize(prefix ...bgp.AddrPrefixInterface) ([]byte, error) { 411 pbuf := make([]byte, 0) 412 totalLen := 0 413 for _, pattr := range e.PathAttributes { 414 var pb []byte 415 var err error 416 // HACK: keeps compatibility 417 switch len(prefix) { 418 case 0: 419 pb, err = pattr.Serialize() 420 case 1: 421 pb, err = pattr.Serialize(&bgp.MarshallingOption{ImplicitPrefix: prefix[0]}) 422 default: 423 return nil, fmt.Errorf("only one prefix should be used") 424 } 425 if err != nil { 426 return nil, err 427 } 428 pbuf = append(pbuf, pb...) 429 totalLen += len(pb) 430 } 431 var buf []byte 432 if e.isAddPath { 433 buf = make([]byte, 12, 12+len(pbuf)) 434 binary.BigEndian.PutUint16(buf, e.PeerIndex) 435 binary.BigEndian.PutUint32(buf[2:], e.OriginatedTime) 436 binary.BigEndian.PutUint32(buf[6:], e.PathIdentifier) 437 binary.BigEndian.PutUint16(buf[10:], uint16(totalLen)) 438 } else { 439 buf = make([]byte, 8, 8+len(pbuf)) 440 binary.BigEndian.PutUint16(buf, e.PeerIndex) 441 binary.BigEndian.PutUint32(buf[2:], e.OriginatedTime) 442 binary.BigEndian.PutUint16(buf[6:], uint16(totalLen)) 443 } 444 buf = append(buf, pbuf...) 445 return buf, nil 446 } 447 448 func NewRibEntry(index uint16, time uint32, pathId uint32, pathAttrs []bgp.PathAttributeInterface, isAddPath bool) *RibEntry { 449 return &RibEntry{ 450 PeerIndex: index, 451 OriginatedTime: time, 452 PathIdentifier: pathId, 453 PathAttributes: pathAttrs, 454 isAddPath: isAddPath, 455 } 456 } 457 458 func (e *RibEntry) String() string { 459 if e.isAddPath { 460 return fmt.Sprintf("RIB_ENTRY: PeerIndex [%d] OriginatedTime [%d] PathIdentifier[%d] PathAttributes [%v]", e.PeerIndex, e.OriginatedTime, e.PathIdentifier, e.PathAttributes) 461 } else { 462 return fmt.Sprintf("RIB_ENTRY: PeerIndex [%d] OriginatedTime [%d] PathAttributes [%v]", e.PeerIndex, e.OriginatedTime, e.PathAttributes) 463 } 464 465 } 466 467 type Rib struct { 468 SequenceNumber uint32 469 Prefix bgp.AddrPrefixInterface 470 Entries []*RibEntry 471 RouteFamily bgp.RouteFamily 472 isAddPath bool 473 } 474 475 func (u *Rib) DecodeFromBytes(data []byte) error { 476 if len(data) < 4 { 477 return fmt.Errorf("not all RibIpv4Unicast message bytes available") 478 } 479 u.SequenceNumber = binary.BigEndian.Uint32(data[:4]) 480 data = data[4:] 481 afi, safi := bgp.RouteFamilyToAfiSafi(u.RouteFamily) 482 if afi == 0 && safi == 0 { 483 afi = binary.BigEndian.Uint16(data[:2]) 484 safi = data[2] 485 data = data[3:] 486 } 487 prefix, err := bgp.NewPrefixFromRouteFamily(afi, safi) 488 if err != nil { 489 return err 490 } 491 err = prefix.DecodeFromBytes(data) 492 if err != nil { 493 return err 494 } 495 u.Prefix = prefix 496 data = data[prefix.Len():] 497 entryNum := binary.BigEndian.Uint16(data[:2]) 498 data = data[2:] 499 u.Entries = make([]*RibEntry, 0, entryNum) 500 for i := 0; i < int(entryNum); i++ { 501 e := &RibEntry{ 502 isAddPath: u.isAddPath, 503 } 504 data, err = e.DecodeFromBytes(data, prefix) 505 if err != nil { 506 return err 507 } 508 u.Entries = append(u.Entries, e) 509 } 510 return nil 511 } 512 513 func (u *Rib) Serialize() ([]byte, error) { 514 buf := make([]byte, 4) 515 binary.BigEndian.PutUint32(buf, u.SequenceNumber) 516 rf := bgp.AfiSafiToRouteFamily(u.Prefix.AFI(), u.Prefix.SAFI()) 517 switch rf { 518 case bgp.RF_IPv4_UC, bgp.RF_IPv4_MC, bgp.RF_IPv6_UC, bgp.RF_IPv6_MC: 519 default: 520 var bbuf [2]byte 521 binary.BigEndian.PutUint16(bbuf[:], u.Prefix.AFI()) 522 buf = append(buf, bbuf[:]...) 523 buf = append(buf, u.Prefix.SAFI()) 524 } 525 bbuf, err := u.Prefix.Serialize() 526 if err != nil { 527 return nil, err 528 } 529 buf = append(buf, bbuf...) 530 bbuf, err = packValues([]interface{}{uint16(len(u.Entries))}) 531 if err != nil { 532 return nil, err 533 } 534 buf = append(buf, bbuf...) 535 for _, entry := range u.Entries { 536 bbuf, err = entry.Serialize(u.Prefix) 537 if err != nil { 538 return nil, err 539 } 540 buf = append(buf, bbuf...) 541 } 542 return buf, nil 543 } 544 545 func NewRib(seq uint32, prefix bgp.AddrPrefixInterface, entries []*RibEntry) *Rib { 546 rf := bgp.AfiSafiToRouteFamily(prefix.AFI(), prefix.SAFI()) 547 return &Rib{ 548 SequenceNumber: seq, 549 Prefix: prefix, 550 Entries: entries, 551 RouteFamily: rf, 552 isAddPath: entries[0].isAddPath, 553 } 554 } 555 556 func (u *Rib) String() string { 557 return fmt.Sprintf("RIB: Seq [%d] Prefix [%s] Entries [%s]", u.SequenceNumber, u.Prefix, u.Entries) 558 } 559 560 type GeoPeer struct { 561 Type uint8 562 BgpId net.IP 563 Latitude float32 564 Longitude float32 565 } 566 567 func (p *GeoPeer) DecodeFromBytes(data []byte) ([]byte, error) { 568 if len(data) < 13 { 569 return nil, fmt.Errorf("not all GeoPeer bytes are available") 570 } 571 // Peer IP Address and Peer AS should not be included 572 p.Type = uint8(data[0]) 573 if p.Type != uint8(0) { 574 return nil, fmt.Errorf("unsupported peer type for GeoPeer: %d", p.Type) 575 } 576 p.BgpId = net.IP(data[1:5]) 577 p.Latitude = math.Float32frombits(binary.BigEndian.Uint32(data[5:9])) 578 p.Longitude = math.Float32frombits(binary.BigEndian.Uint32(data[9:13])) 579 return data[13:], nil 580 } 581 582 func (p *GeoPeer) Serialize() ([]byte, error) { 583 buf := make([]byte, 13) 584 buf[0] = uint8(0) // Peer IP Address and Peer AS should not be included 585 bgpId := p.BgpId.To4() 586 if bgpId == nil { 587 return nil, fmt.Errorf("invalid BgpId: %s", p.BgpId) 588 } 589 copy(buf[1:5], bgpId) 590 binary.BigEndian.PutUint32(buf[5:9], math.Float32bits(p.Latitude)) 591 binary.BigEndian.PutUint32(buf[9:13], math.Float32bits(p.Longitude)) 592 return buf, nil 593 } 594 595 func NewGeoPeer(bgpid string, latitude float32, longitude float32) *GeoPeer { 596 return &GeoPeer{ 597 Type: 0, // Peer IP Address and Peer AS should not be included 598 BgpId: net.ParseIP(bgpid).To4(), 599 Latitude: latitude, 600 Longitude: longitude, 601 } 602 } 603 604 func (p *GeoPeer) String() string { 605 return fmt.Sprintf("PEER ENTRY: ID [%s] Latitude [%f] Longitude [%f]", p.BgpId, p.Latitude, p.Longitude) 606 } 607 608 type GeoPeerTable struct { 609 CollectorBgpId net.IP 610 CollectorLatitude float32 611 CollectorLongitude float32 612 Peers []*GeoPeer 613 } 614 615 func (t *GeoPeerTable) DecodeFromBytes(data []byte) error { 616 if len(data) < 14 { 617 return fmt.Errorf("not all GeoPeerTable bytes are available") 618 } 619 t.CollectorBgpId = net.IP(data[0:4]) 620 t.CollectorLatitude = math.Float32frombits(binary.BigEndian.Uint32(data[4:8])) 621 t.CollectorLongitude = math.Float32frombits(binary.BigEndian.Uint32(data[8:12])) 622 peerCount := binary.BigEndian.Uint16(data[12:14]) 623 data = data[14:] 624 t.Peers = make([]*GeoPeer, 0, peerCount) 625 var err error 626 for i := 0; i < int(peerCount); i++ { 627 p := &GeoPeer{} 628 if data, err = p.DecodeFromBytes(data); err != nil { 629 return err 630 } 631 t.Peers = append(t.Peers, p) 632 } 633 return nil 634 } 635 636 func (t *GeoPeerTable) Serialize() ([]byte, error) { 637 buf := make([]byte, 14) 638 collectorBgpId := t.CollectorBgpId.To4() 639 if collectorBgpId == nil { 640 return nil, fmt.Errorf("invalid CollectorBgpId: %s", t.CollectorBgpId) 641 } 642 copy(buf[0:4], collectorBgpId) 643 binary.BigEndian.PutUint32(buf[4:8], math.Float32bits(t.CollectorLatitude)) 644 binary.BigEndian.PutUint32(buf[8:12], math.Float32bits(t.CollectorLongitude)) 645 binary.BigEndian.PutUint16(buf[12:14], uint16(len(t.Peers))) 646 for _, peer := range t.Peers { 647 pbuf, err := peer.Serialize() 648 if err != nil { 649 return nil, err 650 } 651 buf = append(buf, pbuf...) 652 } 653 return buf, nil 654 } 655 656 func NewGeoPeerTable(bgpid string, latitude float32, longitude float32, peers []*GeoPeer) *GeoPeerTable { 657 return &GeoPeerTable{ 658 CollectorBgpId: net.ParseIP(bgpid).To4(), 659 CollectorLatitude: latitude, 660 CollectorLongitude: longitude, 661 Peers: peers, 662 } 663 } 664 665 func (t *GeoPeerTable) String() string { 666 return fmt.Sprintf("GEO_PEER_TABLE: CollectorBgpId [%s] CollectorLatitude [%f] CollectorLongitude [%f] Peers [%s]", t.CollectorBgpId, t.CollectorLatitude, t.CollectorLongitude, t.Peers) 667 } 668 669 type BGP4MPHeader struct { 670 PeerAS uint32 671 LocalAS uint32 672 InterfaceIndex uint16 673 AddressFamily uint16 674 PeerIpAddress net.IP 675 LocalIpAddress net.IP 676 isAS4 bool 677 } 678 679 func (m *BGP4MPHeader) decodeFromBytes(data []byte) ([]byte, error) { 680 if m.isAS4 && len(data) < 8 { 681 return nil, errors.New("not all BGP4MPMessageAS4 bytes available") 682 } else if !m.isAS4 && len(data) < 4 { 683 return nil, errors.New("not all BGP4MPMessageAS bytes available") 684 } 685 686 if m.isAS4 { 687 m.PeerAS = binary.BigEndian.Uint32(data[:4]) 688 m.LocalAS = binary.BigEndian.Uint32(data[4:8]) 689 data = data[8:] 690 } else { 691 m.PeerAS = uint32(binary.BigEndian.Uint16(data[:2])) 692 m.LocalAS = uint32(binary.BigEndian.Uint16(data[2:4])) 693 data = data[4:] 694 } 695 m.InterfaceIndex = binary.BigEndian.Uint16(data[:2]) 696 m.AddressFamily = binary.BigEndian.Uint16(data[2:4]) 697 switch m.AddressFamily { 698 case bgp.AFI_IP: 699 m.PeerIpAddress = net.IP(data[4:8]).To4() 700 m.LocalIpAddress = net.IP(data[8:12]).To4() 701 data = data[12:] 702 case bgp.AFI_IP6: 703 m.PeerIpAddress = net.IP(data[4:20]) 704 m.LocalIpAddress = net.IP(data[20:36]) 705 data = data[36:] 706 default: 707 return nil, fmt.Errorf("unsupported address family: %d", m.AddressFamily) 708 } 709 return data, nil 710 } 711 712 func (m *BGP4MPHeader) serialize() ([]byte, error) { 713 var values []interface{} 714 if m.isAS4 { 715 values = []interface{}{m.PeerAS, m.LocalAS, m.InterfaceIndex, m.AddressFamily} 716 } else { 717 values = []interface{}{uint16(m.PeerAS), uint16(m.LocalAS), m.InterfaceIndex, m.AddressFamily} 718 } 719 buf, err := packValues(values) 720 if err != nil { 721 return nil, err 722 } 723 var bbuf []byte 724 switch m.AddressFamily { 725 case bgp.AFI_IP: 726 bbuf = make([]byte, 8) 727 copy(bbuf, m.PeerIpAddress.To4()) 728 copy(bbuf[4:], m.LocalIpAddress.To4()) 729 case bgp.AFI_IP6: 730 bbuf = make([]byte, 32) 731 copy(bbuf, m.PeerIpAddress) 732 copy(bbuf[16:], m.LocalIpAddress) 733 default: 734 return nil, fmt.Errorf("unsupported address family: %d", m.AddressFamily) 735 } 736 return append(buf, bbuf...), nil 737 } 738 739 func newBGP4MPHeader(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool) (*BGP4MPHeader, error) { 740 var af uint16 741 paddr := net.ParseIP(peerip).To4() 742 laddr := net.ParseIP(localip).To4() 743 if paddr != nil && laddr != nil { 744 af = bgp.AFI_IP 745 } else { 746 paddr = net.ParseIP(peerip).To16() 747 laddr = net.ParseIP(localip).To16() 748 if paddr != nil && laddr != nil { 749 af = bgp.AFI_IP6 750 } else { 751 return nil, fmt.Errorf("peer IP Address and Local IP Address must have the same address family") 752 } 753 } 754 return &BGP4MPHeader{ 755 PeerAS: peeras, 756 LocalAS: localas, 757 InterfaceIndex: intfindex, 758 AddressFamily: af, 759 PeerIpAddress: paddr, 760 LocalIpAddress: laddr, 761 isAS4: isAS4, 762 }, nil 763 } 764 765 type BGP4MPStateChange struct { 766 *BGP4MPHeader 767 OldState BGPState 768 NewState BGPState 769 } 770 771 func (m *BGP4MPStateChange) DecodeFromBytes(data []byte) error { 772 rest, err := m.decodeFromBytes(data) 773 if err != nil { 774 return err 775 } 776 if len(rest) < 4 { 777 return fmt.Errorf("not all BGP4MPStateChange bytes available") 778 } 779 m.OldState = BGPState(binary.BigEndian.Uint16(rest[:2])) 780 m.NewState = BGPState(binary.BigEndian.Uint16(rest[2:4])) 781 return nil 782 } 783 784 func (m *BGP4MPStateChange) Serialize() ([]byte, error) { 785 buf, err := m.serialize() 786 if err != nil { 787 return nil, err 788 } 789 bbuf, err := packValues([]interface{}{m.OldState, m.NewState}) 790 if err != nil { 791 return nil, err 792 } 793 return append(buf, bbuf...), nil 794 } 795 796 func NewBGP4MPStateChange(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, oldstate, newstate BGPState) *BGP4MPStateChange { 797 header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4) 798 return &BGP4MPStateChange{ 799 BGP4MPHeader: header, 800 OldState: oldstate, 801 NewState: newstate, 802 } 803 } 804 805 type BGP4MPMessage struct { 806 *BGP4MPHeader 807 BGPMessage *bgp.BGPMessage 808 BGPMessagePayload []byte 809 isLocal bool 810 isAddPath bool 811 } 812 813 func (m *BGP4MPMessage) DecodeFromBytes(data []byte) error { 814 rest, err := m.decodeFromBytes(data) 815 if err != nil { 816 return err 817 } 818 819 if len(rest) < bgp.BGP_HEADER_LENGTH { 820 return fmt.Errorf("not all BGP4MPMessageAS4 bytes available") 821 } 822 823 msg, err := bgp.ParseBGPMessage(rest) 824 if err != nil { 825 return err 826 } 827 m.BGPMessage = msg 828 return nil 829 } 830 831 func (m *BGP4MPMessage) Serialize() ([]byte, error) { 832 buf, err := m.serialize() 833 if err != nil { 834 return nil, err 835 } 836 if m.BGPMessagePayload != nil { 837 return append(buf, m.BGPMessagePayload...), nil 838 } 839 bbuf, err := m.BGPMessage.Serialize() 840 if err != nil { 841 return nil, err 842 } 843 return append(buf, bbuf...), nil 844 } 845 846 func NewBGP4MPMessage(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, msg *bgp.BGPMessage) *BGP4MPMessage { 847 header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4) 848 return &BGP4MPMessage{ 849 BGP4MPHeader: header, 850 BGPMessage: msg, 851 } 852 } 853 854 func NewBGP4MPMessageLocal(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, msg *bgp.BGPMessage) *BGP4MPMessage { 855 header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4) 856 return &BGP4MPMessage{ 857 BGP4MPHeader: header, 858 BGPMessage: msg, 859 isLocal: true, 860 } 861 } 862 863 func NewBGP4MPMessageAddPath(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, msg *bgp.BGPMessage) *BGP4MPMessage { 864 header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4) 865 return &BGP4MPMessage{ 866 BGP4MPHeader: header, 867 BGPMessage: msg, 868 isAddPath: true, 869 } 870 } 871 872 func NewBGP4MPMessageLocalAddPath(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, msg *bgp.BGPMessage) *BGP4MPMessage { 873 header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4) 874 return &BGP4MPMessage{ 875 BGP4MPHeader: header, 876 BGPMessage: msg, 877 isLocal: true, 878 isAddPath: true, 879 } 880 } 881 882 func (m *BGP4MPMessage) String() string { 883 title := "BGP4MP_MSG" 884 if m.isAS4 { 885 title += "_AS4" 886 } 887 if m.isLocal { 888 title += "_LOCAL" 889 } 890 if m.isAddPath { 891 title += "_ADDPATH" 892 } 893 return fmt.Sprintf("%s: PeerAS [%d] LocalAS [%d] InterfaceIndex [%d] PeerIP [%s] LocalIP [%s] BGPMessage [%v]", title, m.PeerAS, m.LocalAS, m.InterfaceIndex, m.PeerIpAddress, m.LocalIpAddress, m.BGPMessage) 894 } 895 896 // This function can be passed into a bufio.Scanner.Split() to read buffered mrt msgs 897 func SplitMrt(data []byte, atEOF bool) (advance int, token []byte, err error) { 898 if atEOF && len(data) == 0 { 899 return 0, nil, nil 900 } 901 if cap(data) < MRT_COMMON_HEADER_LEN { // read more 902 return 0, nil, nil 903 } 904 //this reads the data 905 hdr := &MRTHeader{} 906 errh := hdr.DecodeFromBytes(data[:MRT_COMMON_HEADER_LEN]) 907 if errh != nil { 908 return 0, nil, errh 909 } 910 totlen := int(hdr.Len + MRT_COMMON_HEADER_LEN) 911 if len(data) < totlen { //need to read more 912 return 0, nil, nil 913 } 914 return totlen, data[0:totlen], nil 915 } 916 917 func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) { 918 if len(data) < int(h.Len) { 919 return nil, fmt.Errorf("not all MRT message bytes available. expected: %d, actual: %d", int(h.Len), len(data)) 920 } 921 msg := &MRTMessage{Header: *h} 922 switch h.Type { 923 case TABLE_DUMPv2: 924 subType := MRTSubTypeTableDumpv2(h.SubType) 925 rf := bgp.RouteFamily(0) 926 isAddPath := false 927 switch subType { 928 case PEER_INDEX_TABLE: 929 msg.Body = &PeerIndexTable{} 930 case RIB_IPV4_UNICAST: 931 rf = bgp.RF_IPv4_UC 932 case RIB_IPV4_MULTICAST: 933 rf = bgp.RF_IPv4_MC 934 case RIB_IPV6_UNICAST: 935 rf = bgp.RF_IPv6_UC 936 case RIB_IPV6_MULTICAST: 937 rf = bgp.RF_IPv6_MC 938 case RIB_GENERIC: 939 case GEO_PEER_TABLE: 940 msg.Body = &GeoPeerTable{} 941 case RIB_IPV4_UNICAST_ADDPATH: 942 rf = bgp.RF_IPv4_UC 943 isAddPath = true 944 case RIB_IPV4_MULTICAST_ADDPATH: 945 rf = bgp.RF_IPv4_MC 946 isAddPath = true 947 case RIB_IPV6_UNICAST_ADDPATH: 948 rf = bgp.RF_IPv6_UC 949 isAddPath = true 950 case RIB_IPV6_MULTICAST_ADDPATH: 951 rf = bgp.RF_IPv6_MC 952 isAddPath = true 953 case RIB_GENERIC_ADDPATH: 954 isAddPath = true 955 default: 956 return nil, fmt.Errorf("unsupported table dumpv2 subtype: %v", subType) 957 } 958 959 if msg.Body == nil { 960 msg.Body = &Rib{ 961 RouteFamily: rf, 962 isAddPath: isAddPath, 963 } 964 } 965 case BGP4MP: 966 subType := MRTSubTypeBGP4MP(h.SubType) 967 isAS4 := true 968 switch subType { 969 case STATE_CHANGE: 970 isAS4 = false 971 fallthrough 972 case STATE_CHANGE_AS4: 973 msg.Body = &BGP4MPStateChange{ 974 BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4}, 975 } 976 case MESSAGE: 977 isAS4 = false 978 fallthrough 979 case MESSAGE_AS4: 980 msg.Body = &BGP4MPMessage{ 981 BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4}, 982 } 983 case MESSAGE_LOCAL: 984 isAS4 = false 985 fallthrough 986 case MESSAGE_AS4_LOCAL: 987 msg.Body = &BGP4MPMessage{ 988 BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4}, 989 isLocal: true, 990 } 991 case MESSAGE_ADDPATH: 992 isAS4 = false 993 fallthrough 994 case MESSAGE_AS4_ADDPATH: 995 msg.Body = &BGP4MPMessage{ 996 BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4}, 997 isAddPath: true, 998 } 999 case MESSAGE_LOCAL_ADDPATH: 1000 isAS4 = false 1001 fallthrough 1002 case MESSAGE_AS4_LOCAL_ADDPATH: 1003 msg.Body = &BGP4MPMessage{ 1004 BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4}, 1005 isLocal: true, 1006 isAddPath: true, 1007 } 1008 default: 1009 return nil, fmt.Errorf("unsupported bgp4mp subtype: %v", subType) 1010 } 1011 default: 1012 return nil, fmt.Errorf("unsupported type: %v", h.Type) 1013 } 1014 err := msg.Body.DecodeFromBytes(data) 1015 if err != nil { 1016 return nil, err 1017 } 1018 return msg, nil 1019 }