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  }