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