summaryrefslogtreecommitdiffhomepage
path: root/packet/bgp
diff options
context:
space:
mode:
Diffstat (limited to 'packet/bgp')
-rw-r--r--packet/bgp/mrt.go798
-rw-r--r--packet/bgp/mrt_test.go220
2 files changed, 0 insertions, 1018 deletions
diff --git a/packet/bgp/mrt.go b/packet/bgp/mrt.go
deleted file mode 100644
index 15dbc839..00000000
--- a/packet/bgp/mrt.go
+++ /dev/null
@@ -1,798 +0,0 @@
-// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package bgp
-
-import (
- "bytes"
- "encoding/binary"
- "fmt"
- "math"
- "net"
- "time"
-)
-
-const (
- MRT_COMMON_HEADER_LEN = 12
-)
-
-type MRTType uint16
-
-const (
- NULL MRTType = 0 // deprecated
- START MRTType = 1 // deprecated
- DIE MRTType = 2 // deprecated
- I_AM_DEAD MRTType = 3 // deprecated
- PEER_DOWN MRTType = 4 // deprecated
- BGP MRTType = 5 // deprecated
- RIP MRTType = 6 // deprecated
- IDRP MRTType = 7 // deprecated
- RIPNG MRTType = 8 // deprecated
- BGP4PLUS MRTType = 9 // deprecated
- BGP4PLUS01 MRTType = 10 // deprecated
- OSPFv2 MRTType = 11
- TABLE_DUMP MRTType = 12
- TABLE_DUMPv2 MRTType = 13
- BGP4MP MRTType = 16
- BGP4MP_ET MRTType = 17
- ISIS MRTType = 32
- ISIS_ET MRTType = 33
- OSPFv3 MRTType = 48
- OSPFv3_ET MRTType = 49
-)
-
-type MRTSubTyper interface {
- ToUint16() uint16
-}
-
-type MRTSubTypeTableDumpv2 uint16
-
-const (
- PEER_INDEX_TABLE MRTSubTypeTableDumpv2 = 1
- RIB_IPV4_UNICAST MRTSubTypeTableDumpv2 = 2
- RIB_IPV4_MULTICAST MRTSubTypeTableDumpv2 = 3
- RIB_IPV6_UNICAST MRTSubTypeTableDumpv2 = 4
- RIB_IPV6_MULTICAST MRTSubTypeTableDumpv2 = 5
- RIB_GENERIC MRTSubTypeTableDumpv2 = 6
-)
-
-func (t MRTSubTypeTableDumpv2) ToUint16() uint16 {
- return uint16(t)
-}
-
-type MRTSubTypeBGP4MP uint16
-
-const (
- STATE_CHANGE MRTSubTypeBGP4MP = 0
- MESSAGE MRTSubTypeBGP4MP = 1
- MESSAGE_AS4 MRTSubTypeBGP4MP = 4
- STATE_CHANGE_AS4 MRTSubTypeBGP4MP = 5
- MESSAGE_LOCAL MRTSubTypeBGP4MP = 6
- MESSAGE_AS4_LOCAL MRTSubTypeBGP4MP = 7
-)
-
-func (t MRTSubTypeBGP4MP) ToUint16() uint16 {
- return uint16(t)
-}
-
-type BGPState uint16
-
-const (
- IDLE BGPState = 1
- CONNECT BGPState = 2
- ACTIVE BGPState = 3
- OPENSENT BGPState = 4
- OPENCONFIRM BGPState = 5
- ESTABLISHED BGPState = 6
-)
-
-func packValues(values []interface{}) ([]byte, error) {
- b := new(bytes.Buffer)
- for _, v := range values {
- err := binary.Write(b, binary.BigEndian, v)
- if err != nil {
- return nil, err
- }
- }
- return b.Bytes(), nil
-}
-
-type MRTHeader struct {
- Timestamp uint32
- Type MRTType
- SubType uint16
- Len uint32
-}
-
-func (h *MRTHeader) DecodeFromBytes(data []byte) error {
- if len(data) < MRT_COMMON_HEADER_LEN {
- return fmt.Errorf("not all MRTHeader bytes are available. expected: %d, actual: %d", MRT_COMMON_HEADER_LEN, len(data))
- }
- h.Timestamp = binary.BigEndian.Uint32(data[:4])
- h.Type = MRTType(binary.BigEndian.Uint16(data[4:6]))
- h.SubType = binary.BigEndian.Uint16(data[6:8])
- h.Len = binary.BigEndian.Uint32(data[8:12])
- return nil
-}
-
-func (h *MRTHeader) Serialize() ([]byte, error) {
- return packValues([]interface{}{h.Timestamp, h.Type, h.SubType, h.Len})
-}
-
-func NewMRTHeader(timestamp uint32, t MRTType, subtype MRTSubTyper, l uint32) (*MRTHeader, error) {
- return &MRTHeader{
- Timestamp: timestamp,
- Type: t,
- SubType: subtype.ToUint16(),
- Len: l,
- }, nil
-}
-
-func (h *MRTHeader) GetTime() time.Time {
- t := int64(h.Timestamp)
- return time.Unix(t, 0)
-}
-
-type MRTMessage struct {
- Header MRTHeader
- Body Body
-}
-
-func (m *MRTMessage) Serialize() ([]byte, error) {
- buf, err := m.Body.Serialize()
- if err != nil {
- return nil, err
- }
- m.Header.Len = uint32(len(buf))
- bbuf, err := m.Header.Serialize()
- if err != nil {
- return nil, err
- }
- return append(bbuf, buf...), nil
-}
-
-func NewMRTMessage(timestamp uint32, t MRTType, subtype MRTSubTyper, body Body) (*MRTMessage, error) {
- header, err := NewMRTHeader(timestamp, t, subtype, 0)
- if err != nil {
- return nil, err
- }
- return &MRTMessage{
- Header: *header,
- Body: body,
- }, nil
-}
-
-type Body interface {
- DecodeFromBytes([]byte) error
- Serialize() ([]byte, error)
-}
-
-type Peer struct {
- Type uint8
- BgpId net.IP
- IpAddress net.IP
- AS uint32
-}
-
-func (p *Peer) DecodeFromBytes(data []byte) ([]byte, error) {
- notAllBytesAvail := fmt.Errorf("not all Peer bytes are available")
- if len(data) < 5 {
- return nil, notAllBytesAvail
- }
- p.Type = uint8(data[0])
- p.BgpId = net.IP(data[1:5])
- data = data[5:]
-
- if p.Type&1 > 0 {
- if len(data) < 16 {
- return nil, notAllBytesAvail
- }
- p.IpAddress = net.IP(data[:16])
- data = data[16:]
- } else {
- if len(data) < 4 {
- return nil, notAllBytesAvail
- }
- p.IpAddress = net.IP(data[:4])
- data = data[4:]
- }
-
- if p.Type&(1<<1) > 0 {
- if len(data) < 4 {
- return nil, notAllBytesAvail
- }
- p.AS = binary.BigEndian.Uint32(data[:4])
- data = data[4:]
- } else {
- if len(data) < 2 {
- return nil, notAllBytesAvail
- }
- p.AS = uint32(binary.BigEndian.Uint16(data[:2]))
- data = data[2:]
- }
-
- return data, nil
-}
-
-func (p *Peer) Serialize() ([]byte, error) {
- var err error
- var bbuf []byte
- buf := make([]byte, 5)
- buf[0] = uint8(p.Type)
- copy(buf[1:], p.BgpId.To4())
- if p.Type&1 > 0 {
- buf = append(buf, p.IpAddress.To16()...)
- } else {
- buf = append(buf, p.IpAddress.To4()...)
- }
- if p.Type&(1<<1) > 0 {
- bbuf, err = packValues([]interface{}{p.AS})
- } else {
- if p.AS > uint32(math.MaxUint16) {
- return nil, fmt.Errorf("AS number is beyond 2 octet. %d > %d", p.AS, math.MaxUint16)
- }
- bbuf, err = packValues([]interface{}{uint16(p.AS)})
- }
- if err != nil {
- return nil, err
- }
- return append(buf, bbuf...), nil
-}
-
-func NewPeer(bgpid string, ipaddr string, asn uint32, isAS4 bool) *Peer {
- t := 0
- addr := net.ParseIP(ipaddr).To4()
- if addr == nil {
- t |= 1
- addr = net.ParseIP(ipaddr).To16()
- }
- if isAS4 {
- t |= (1 << 1)
- }
- return &Peer{
- Type: uint8(t),
- BgpId: net.ParseIP(bgpid).To4(),
- IpAddress: addr,
- AS: asn,
- }
-}
-
-func (p *Peer) String() string {
- return fmt.Sprintf("PEER ENTRY: ID [%s] Addr [%s] AS [%d]", p.BgpId, p.IpAddress, p.AS)
-}
-
-type PeerIndexTable struct {
- CollectorBgpId net.IP
- ViewName string
- Peers []*Peer
-}
-
-func (t *PeerIndexTable) DecodeFromBytes(data []byte) error {
- notAllBytesAvail := fmt.Errorf("not all PeerIndexTable bytes are available")
- if len(data) < 6 {
- return notAllBytesAvail
- }
- t.CollectorBgpId = net.IP(data[:4])
- viewLen := binary.BigEndian.Uint16(data[4:6])
- if len(data) < 6+int(viewLen) {
- return notAllBytesAvail
- }
- t.ViewName = string(data[6 : 6+viewLen])
-
- data = data[6+viewLen:]
-
- if len(data) < 2 {
- return notAllBytesAvail
- }
- peerNum := binary.BigEndian.Uint16(data[:2])
- data = data[2:]
- t.Peers = make([]*Peer, 0, peerNum)
- var err error
- for i := 0; i < int(peerNum); i++ {
- p := &Peer{}
- data, err = p.DecodeFromBytes(data)
- if err != nil {
- return err
- }
- t.Peers = append(t.Peers, p)
- }
-
- return nil
-}
-
-func (t *PeerIndexTable) Serialize() ([]byte, error) {
- buf := make([]byte, 8+len(t.ViewName))
- copy(buf, t.CollectorBgpId.To4())
- binary.BigEndian.PutUint16(buf[4:], uint16(len(t.ViewName)))
- copy(buf[6:], t.ViewName)
- binary.BigEndian.PutUint16(buf[6+len(t.ViewName):], uint16(len(t.Peers)))
- for _, peer := range t.Peers {
- bbuf, err := peer.Serialize()
- if err != nil {
- return nil, err
- }
- buf = append(buf, bbuf...)
- }
- return buf, nil
-}
-
-func NewPeerIndexTable(bgpid string, viewname string, peers []*Peer) *PeerIndexTable {
- return &PeerIndexTable{
- CollectorBgpId: net.ParseIP(bgpid).To4(),
- ViewName: viewname,
- Peers: peers,
- }
-}
-
-func (t *PeerIndexTable) String() string {
- return fmt.Sprintf("PEER_INDEX_TABLE: CollectorBgpId [%s] ViewName [%s] Peers [%s]", t.CollectorBgpId, t.ViewName, t.Peers)
-}
-
-type RibEntry struct {
- PeerIndex uint16
- OriginatedTime uint32
- PathAttributes []PathAttributeInterface
-}
-
-func (e *RibEntry) DecodeFromBytes(data []byte) ([]byte, error) {
- notAllBytesAvail := fmt.Errorf("not all RibEntry bytes are available")
- if len(data) < 8 {
- return nil, notAllBytesAvail
- }
- e.PeerIndex = binary.BigEndian.Uint16(data[:2])
- e.OriginatedTime = binary.BigEndian.Uint32(data[2:6])
- totalLen := binary.BigEndian.Uint16(data[6:8])
- data = data[8:]
- for attrLen := totalLen; attrLen > 0; {
- p, err := GetPathAttribute(data)
- if err != nil {
- return nil, err
- }
- err = p.DecodeFromBytes(data)
- if err != nil {
- return nil, err
- }
- attrLen -= uint16(p.Len())
- if len(data) < p.Len() {
- return nil, notAllBytesAvail
- }
- data = data[p.Len():]
- e.PathAttributes = append(e.PathAttributes, p)
- }
- return data, nil
-}
-
-func (e *RibEntry) Serialize() ([]byte, error) {
- buf := make([]byte, 8)
- binary.BigEndian.PutUint16(buf, e.PeerIndex)
- binary.BigEndian.PutUint32(buf[2:], e.OriginatedTime)
- totalLen := 0
- binary.BigEndian.PutUint16(buf[6:], uint16(totalLen))
- for _, pattr := range e.PathAttributes {
- // TODO special modification is needed for MP_REACH_NLRI
- // but also Quagga doesn't implement this.
- //
- // RFC 6396 4.3.4
- // There is one exception to the encoding of BGP attributes for the BGP
- // MP_REACH_NLRI attribute (BGP Type Code 14).
- // Since the AFI, SAFI, and NLRI information is already encoded
- // in the RIB Entry Header or RIB_GENERIC Entry Header,
- // only the Next Hop Address Length and Next Hop Address fields are included.
-
- bbuf, err := pattr.Serialize()
- if err != nil {
- return nil, err
- }
- buf = append(buf, bbuf...)
- totalLen += len(bbuf)
- }
- binary.BigEndian.PutUint16(buf[6:], uint16(totalLen))
- return buf, nil
-}
-
-func NewRibEntry(index uint16, time uint32, pathattrs []PathAttributeInterface) *RibEntry {
- return &RibEntry{
- PeerIndex: index,
- OriginatedTime: time,
- PathAttributes: pathattrs,
- }
-}
-
-func (e *RibEntry) String() string {
- return fmt.Sprintf("RIB_ENTRY: PeerIndex [%d] OriginatedTime [%d] PathAttrs [%v]", e.PeerIndex, e.OriginatedTime, e.PathAttributes)
-}
-
-type Rib struct {
- SequenceNumber uint32
- Prefix AddrPrefixInterface
- Entries []*RibEntry
- RouteFamily RouteFamily
-}
-
-func (u *Rib) DecodeFromBytes(data []byte) error {
- if len(data) < 4 {
- return fmt.Errorf("Not all RibIpv4Unicast message bytes available")
- }
- u.SequenceNumber = binary.BigEndian.Uint32(data[:4])
- data = data[4:]
- afi, safi := RouteFamilyToAfiSafi(u.RouteFamily)
- if afi == 0 && safi == 0 {
- afi = binary.BigEndian.Uint16(data[:2])
- safi = data[2]
- data = data[3:]
- }
- prefix, err := NewPrefixFromRouteFamily(afi, safi)
- if err != nil {
- return err
- }
- err = prefix.DecodeFromBytes(data)
- if err != nil {
- return err
- }
- u.Prefix = prefix
- data = data[prefix.Len():]
- entryNum := binary.BigEndian.Uint16(data[:2])
- data = data[2:]
- u.Entries = make([]*RibEntry, 0, entryNum)
- for i := 0; i < int(entryNum); i++ {
- e := &RibEntry{}
- data, err = e.DecodeFromBytes(data)
- if err != nil {
- return err
- }
- u.Entries = append(u.Entries, e)
- }
- return nil
-}
-
-func (u *Rib) Serialize() ([]byte, error) {
- buf := make([]byte, 4)
- binary.BigEndian.PutUint32(buf, u.SequenceNumber)
- rf := AfiSafiToRouteFamily(u.Prefix.AFI(), u.Prefix.SAFI())
- switch rf {
- case RF_IPv4_UC, RF_IPv4_MC, RF_IPv6_UC, RF_IPv6_MC:
- default:
- bbuf := make([]byte, 0, 2)
- binary.BigEndian.PutUint16(bbuf, u.Prefix.AFI())
- buf = append(buf, bbuf...)
- buf = append(buf, u.Prefix.SAFI())
- }
- bbuf, err := u.Prefix.Serialize()
- if err != nil {
- return nil, err
- }
- buf = append(buf, bbuf...)
- bbuf, err = packValues([]interface{}{uint16(len(u.Entries))})
- if err != nil {
- return nil, err
- }
- buf = append(buf, bbuf...)
- for _, entry := range u.Entries {
- bbuf, err = entry.Serialize()
- if err != nil {
- return nil, err
- }
- buf = append(buf, bbuf...)
- }
- return buf, nil
-}
-
-func NewRib(seq uint32, prefix AddrPrefixInterface, entries []*RibEntry) *Rib {
- rf := AfiSafiToRouteFamily(prefix.AFI(), prefix.SAFI())
- return &Rib{
- SequenceNumber: seq,
- Prefix: prefix,
- Entries: entries,
- RouteFamily: rf,
- }
-}
-
-func (u *Rib) String() string {
- return fmt.Sprintf("RIB: Seq [%d] Prefix [%s] Entries [%s]", u.SequenceNumber, u.Prefix, u.Entries)
-}
-
-type BGP4MPHeader struct {
- PeerAS uint32
- LocalAS uint32
- InterfaceIndex uint16
- AddressFamily uint16
- PeerIpAddress net.IP
- LocalIpAddress net.IP
- isAS4 bool
-}
-
-func (m *BGP4MPHeader) decodeFromBytes(data []byte) ([]byte, error) {
- if m.isAS4 && len(data) < 8 {
- return nil, fmt.Errorf("Not all BGP4MPMessageAS4 bytes available")
- } else if !m.isAS4 && len(data) < 4 {
- return nil, fmt.Errorf("Not all BGP4MPMessageAS bytes available")
- }
-
- if m.isAS4 {
- m.PeerAS = binary.BigEndian.Uint32(data[:4])
- m.LocalAS = binary.BigEndian.Uint32(data[4:8])
- data = data[8:]
- } else {
- m.PeerAS = uint32(binary.BigEndian.Uint16(data[:2]))
- m.LocalAS = uint32(binary.BigEndian.Uint16(data[2:4]))
- data = data[4:]
- }
- m.InterfaceIndex = binary.BigEndian.Uint16(data[:2])
- m.AddressFamily = binary.BigEndian.Uint16(data[2:4])
- switch m.AddressFamily {
- case AFI_IP:
- m.PeerIpAddress = net.IP(data[4:8]).To4()
- m.LocalIpAddress = net.IP(data[8:12]).To4()
- data = data[12:]
- case AFI_IP6:
- m.PeerIpAddress = net.IP(data[4:20])
- m.LocalIpAddress = net.IP(data[20:36])
- data = data[36:]
- default:
- return nil, fmt.Errorf("unsupported address family: %d", m.AddressFamily)
- }
- return data, nil
-}
-
-func (m *BGP4MPHeader) serialize() ([]byte, error) {
- var values []interface{}
- if m.isAS4 {
- values = []interface{}{m.PeerAS, m.LocalAS, m.InterfaceIndex, m.AddressFamily}
- } else {
- values = []interface{}{uint16(m.PeerAS), uint16(m.LocalAS), m.InterfaceIndex, m.AddressFamily}
- }
- buf, err := packValues(values)
- if err != nil {
- return nil, err
- }
- var bbuf []byte
- switch m.AddressFamily {
- case AFI_IP:
- bbuf = make([]byte, 8)
- copy(bbuf, m.PeerIpAddress.To4())
- copy(bbuf[4:], m.LocalIpAddress.To4())
- case AFI_IP6:
- bbuf = make([]byte, 32)
- copy(bbuf, m.PeerIpAddress)
- copy(bbuf[16:], m.LocalIpAddress)
- default:
- return nil, fmt.Errorf("unsupported address family: %d", m.AddressFamily)
- }
- return append(buf, bbuf...), nil
-}
-
-func newBGP4MPHeader(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool) (*BGP4MPHeader, error) {
- var af uint16
- paddr := net.ParseIP(peerip).To4()
- laddr := net.ParseIP(localip).To4()
- if paddr != nil && laddr != nil {
- af = AFI_IP
- } else {
- paddr = net.ParseIP(peerip).To16()
- laddr = net.ParseIP(localip).To16()
- if paddr != nil && laddr != nil {
- af = AFI_IP6
- } else {
- return nil, fmt.Errorf("Peer IP Address and Local IP Address must have the same address family")
- }
- }
- return &BGP4MPHeader{
- PeerAS: peeras,
- LocalAS: localas,
- InterfaceIndex: intfindex,
- AddressFamily: af,
- PeerIpAddress: paddr,
- LocalIpAddress: laddr,
- isAS4: isAS4,
- }, nil
-}
-
-type BGP4MPStateChange struct {
- *BGP4MPHeader
- OldState BGPState
- NewState BGPState
-}
-
-func (m *BGP4MPStateChange) DecodeFromBytes(data []byte) error {
- rest, err := m.decodeFromBytes(data)
- if err != nil {
- return err
- }
- if len(rest) < 4 {
- return fmt.Errorf("Not all BGP4MPStateChange bytes available")
- }
- m.OldState = BGPState(binary.BigEndian.Uint16(rest[:2]))
- m.NewState = BGPState(binary.BigEndian.Uint16(rest[2:4]))
- return nil
-}
-
-func (m *BGP4MPStateChange) Serialize() ([]byte, error) {
- buf, err := m.serialize()
- if err != nil {
- return nil, err
- }
- bbuf, err := packValues([]interface{}{m.OldState, m.NewState})
- if err != nil {
- return nil, err
- }
- return append(buf, bbuf...), nil
-}
-
-func NewBGP4MPStateChange(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, oldstate, newstate BGPState) *BGP4MPStateChange {
- header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4)
- return &BGP4MPStateChange{
- BGP4MPHeader: header,
- OldState: oldstate,
- NewState: newstate,
- }
-}
-
-type BGP4MPMessage struct {
- *BGP4MPHeader
- BGPMessage *BGPMessage
- BGPMessagePayload []byte
- isLocal bool
-}
-
-func (m *BGP4MPMessage) DecodeFromBytes(data []byte) error {
- rest, err := m.decodeFromBytes(data)
- if err != nil {
- return err
- }
-
- if len(rest) < BGP_HEADER_LENGTH {
- return fmt.Errorf("Not all BGP4MPMessageAS4 bytes available")
- }
-
- msg, err := ParseBGPMessage(rest)
- if err != nil {
- return err
- }
- m.BGPMessage = msg
- return nil
-}
-
-func (m *BGP4MPMessage) Serialize() ([]byte, error) {
- buf, err := m.serialize()
- if err != nil {
- return nil, err
- }
- if m.BGPMessagePayload != nil {
- return append(buf, m.BGPMessagePayload...), nil
- }
- bbuf, err := m.BGPMessage.Serialize()
- if err != nil {
- return nil, err
- }
- return append(buf, bbuf...), nil
-}
-
-func NewBGP4MPMessage(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, msg *BGPMessage) *BGP4MPMessage {
- header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4)
- return &BGP4MPMessage{
- BGP4MPHeader: header,
- BGPMessage: msg,
- }
-}
-
-func NewBGP4MPMessageLocal(peeras, localas uint32, intfindex uint16, peerip, localip string, isAS4 bool, msg *BGPMessage) *BGP4MPMessage {
- header, _ := newBGP4MPHeader(peeras, localas, intfindex, peerip, localip, isAS4)
- return &BGP4MPMessage{
- BGP4MPHeader: header,
- BGPMessage: msg,
- isLocal: true,
- }
-}
-
-func (m *BGP4MPMessage) String() string {
- title := "BGP4MP_MSG"
- if m.isAS4 {
- title += "_AS4"
- }
- if m.isLocal {
- title += "_LOCAL"
- }
- 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)
-}
-
-//This function can be passed into a bufio.Scanner.Split() to read buffered mrt msgs
-func SplitMrt(data []byte, atEOF bool) (advance int, token []byte, err error) {
- if atEOF && len(data) == 0 {
- return 0, nil, nil
- }
- if cap(data) < MRT_COMMON_HEADER_LEN { // read more
- return 0, nil, nil
- }
- //this reads the data
- hdr := &MRTHeader{}
- errh := hdr.DecodeFromBytes(data[:MRT_COMMON_HEADER_LEN])
- if errh != nil {
- return 0, nil, errh
- }
- totlen := int(hdr.Len + MRT_COMMON_HEADER_LEN)
- if len(data) < totlen { //need to read more
- return 0, nil, nil
- }
- return totlen, data[0:totlen], nil
-}
-
-func ParseMRTBody(h *MRTHeader, data []byte) (*MRTMessage, error) {
- if len(data) < int(h.Len) {
- return nil, fmt.Errorf("Not all MRT message bytes available. expected: %d, actual: %d", int(h.Len), len(data))
- }
- msg := &MRTMessage{Header: *h}
- switch h.Type {
- case TABLE_DUMPv2:
- subType := MRTSubTypeTableDumpv2(h.SubType)
- rf := RouteFamily(0)
- switch subType {
- case PEER_INDEX_TABLE:
- msg.Body = &PeerIndexTable{}
- case RIB_IPV4_UNICAST:
- rf = RF_IPv4_UC
- case RIB_IPV4_MULTICAST:
- rf = RF_IPv4_MC
- case RIB_IPV6_UNICAST:
- rf = RF_IPv6_UC
- case RIB_IPV6_MULTICAST:
- rf = RF_IPv6_MC
- case RIB_GENERIC:
- default:
- return nil, fmt.Errorf("unsupported table dumpv2 subtype: %v\n", subType)
- }
-
- if subType != PEER_INDEX_TABLE {
- msg.Body = &Rib{
- RouteFamily: rf,
- }
- }
- case BGP4MP:
- subType := MRTSubTypeBGP4MP(h.SubType)
- isAS4 := true
- switch subType {
- case STATE_CHANGE:
- isAS4 = false
- fallthrough
- case STATE_CHANGE_AS4:
- msg.Body = &BGP4MPStateChange{
- BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4},
- }
- case MESSAGE:
- isAS4 = false
- fallthrough
- case MESSAGE_AS4:
- msg.Body = &BGP4MPMessage{
- BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4},
- }
- case MESSAGE_LOCAL:
- isAS4 = false
- fallthrough
- case MESSAGE_AS4_LOCAL:
- msg.Body = &BGP4MPMessage{
- BGP4MPHeader: &BGP4MPHeader{isAS4: isAS4},
- isLocal: true,
- }
- default:
- return nil, fmt.Errorf("unsupported bgp4mp subtype: %v\n", subType)
- }
- default:
- return nil, fmt.Errorf("unsupported type: %v\n", h.Type)
- }
- err := msg.Body.DecodeFromBytes(data)
- if err != nil {
- return nil, err
- }
- return msg, nil
-}
diff --git a/packet/bgp/mrt_test.go b/packet/bgp/mrt_test.go
deleted file mode 100644
index 11a233ec..00000000
--- a/packet/bgp/mrt_test.go
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package bgp
-
-import (
- "bufio"
- "bytes"
- "github.com/stretchr/testify/assert"
- "reflect"
- "testing"
- "time"
-)
-
-func TestMrtHdr(t *testing.T) {
- h1, err := NewMRTHeader(10, TABLE_DUMPv2, RIB_IPV4_MULTICAST, 20)
- if err != nil {
- t.Fatal(err)
- }
- b1, err := h1.Serialize()
- if err != nil {
- t.Fatal(err)
- }
- h2 := &MRTHeader{}
- err = h2.DecodeFromBytes(b1)
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(t, reflect.DeepEqual(h1, h2), true)
-}
-
-func TestMrtHdrTime(t *testing.T) {
- h1, err := NewMRTHeader(10, TABLE_DUMPv2, RIB_IPV4_MULTICAST, 20)
- if err != nil {
- t.Fatal(err)
- }
- ttime := time.Unix(10, 0)
- htime := h1.GetTime()
- t.Logf("this timestamp should be 10s after epoch:%v", htime)
- assert.Equal(t, h1.GetTime(), ttime)
-}
-
-func testPeer(t *testing.T, p1 *Peer) {
- b1, err := p1.Serialize()
- if err != nil {
- t.Fatal(err)
- }
- p2 := &Peer{}
- rest, err := p2.DecodeFromBytes(b1)
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(t, len(rest), 0)
- assert.Equal(t, reflect.DeepEqual(p1, p2), true)
-}
-
-func TestMrtPeer(t *testing.T) {
- p := NewPeer("192.168.0.1", "10.0.0.1", 65000, false)
- testPeer(t, p)
-}
-
-func TestMrtPeerv6(t *testing.T) {
- p := NewPeer("192.168.0.1", "2001::1", 65000, false)
- testPeer(t, p)
-}
-
-func TestMrtPeerAS4(t *testing.T) {
- p := NewPeer("192.168.0.1", "2001::1", 135500, true)
- testPeer(t, p)
-}
-
-func TestMrtPeerIndexTable(t *testing.T) {
- p1 := NewPeer("192.168.0.1", "10.0.0.1", 65000, false)
- p2 := NewPeer("192.168.0.1", "2001::1", 65000, false)
- p3 := NewPeer("192.168.0.1", "2001::1", 135500, true)
- pt1 := NewPeerIndexTable("192.168.0.1", "test", []*Peer{p1, p2, p3})
- b1, err := pt1.Serialize()
- if err != nil {
- t.Fatal(err)
- }
- pt2 := &PeerIndexTable{}
- err = pt2.DecodeFromBytes(b1)
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(t, reflect.DeepEqual(pt1, pt2), true)
-}
-
-func TestMrtRibEntry(t *testing.T) {
- aspath1 := []AsPathParamInterface{
- NewAsPathParam(2, []uint16{1000}),
- NewAsPathParam(1, []uint16{1001, 1002}),
- NewAsPathParam(2, []uint16{1003, 1004}),
- }
-
- p := []PathAttributeInterface{
- NewPathAttributeOrigin(3),
- NewPathAttributeAsPath(aspath1),
- NewPathAttributeNextHop("129.1.1.2"),
- NewPathAttributeMultiExitDisc(1 << 20),
- NewPathAttributeLocalPref(1 << 22),
- }
-
- e1 := NewRibEntry(1, uint32(time.Now().Unix()), p)
- b1, err := e1.Serialize()
- if err != nil {
- t.Fatal(err)
- }
-
- e2 := &RibEntry{}
- rest, err := e2.DecodeFromBytes(b1)
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(t, len(rest), 0)
- assert.Equal(t, reflect.DeepEqual(e1, e2), true)
-}
-
-func TestMrtRib(t *testing.T) {
- aspath1 := []AsPathParamInterface{
- NewAsPathParam(2, []uint16{1000}),
- NewAsPathParam(1, []uint16{1001, 1002}),
- NewAsPathParam(2, []uint16{1003, 1004}),
- }
-
- p := []PathAttributeInterface{
- NewPathAttributeOrigin(3),
- NewPathAttributeAsPath(aspath1),
- NewPathAttributeNextHop("129.1.1.2"),
- NewPathAttributeMultiExitDisc(1 << 20),
- NewPathAttributeLocalPref(1 << 22),
- }
-
- e1 := NewRibEntry(1, uint32(time.Now().Unix()), p)
- e2 := NewRibEntry(2, uint32(time.Now().Unix()), p)
- e3 := NewRibEntry(3, uint32(time.Now().Unix()), p)
-
- r1 := NewRib(1, NewIPAddrPrefix(24, "192.168.0.0"), []*RibEntry{e1, e2, e3})
- b1, err := r1.Serialize()
- if err != nil {
- t.Fatal(err)
- }
- r2 := &Rib{
- RouteFamily: RF_IPv4_UC,
- }
- err = r2.DecodeFromBytes(b1)
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(t, reflect.DeepEqual(r1, r2), true)
-}
-
-func TestMrtBgp4mpStateChange(t *testing.T) {
- c1 := NewBGP4MPStateChange(65000, 65001, 1, "192.168.0.1", "192.168.0.2", false, ACTIVE, ESTABLISHED)
- b1, err := c1.Serialize()
- if err != nil {
- t.Fatal(err)
- }
- c2 := &BGP4MPStateChange{BGP4MPHeader: &BGP4MPHeader{}}
- err = c2.DecodeFromBytes(b1)
- if err != nil {
- t.Fatal(err)
- }
- _, err = c2.Serialize()
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(t, reflect.DeepEqual(c1, c2), true)
-}
-
-func TestMrtBgp4mpMessage(t *testing.T) {
- msg := NewBGPKeepAliveMessage()
- m1 := NewBGP4MPMessage(65000, 65001, 1, "192.168.0.1", "192.168.0.2", false, msg)
- b1, err := m1.Serialize()
- if err != nil {
- t.Fatal(err)
- }
- m2 := &BGP4MPMessage{BGP4MPHeader: &BGP4MPHeader{}}
- err = m2.DecodeFromBytes(b1)
- if err != nil {
- t.Fatal(err)
- }
- assert.Equal(t, reflect.DeepEqual(m1, m2), true)
-}
-
-func TestMrtSplit(t *testing.T) {
- var b bytes.Buffer
- numwrite, numread := 10, 0
- for i := 0; i < numwrite; i++ {
- msg := NewBGPKeepAliveMessage()
- m1 := NewBGP4MPMessage(65000, 65001, 1, "192.168.0.1", "192.168.0.2", false, msg)
- mm, _ := NewMRTMessage(1234, BGP4MP, MESSAGE, m1)
- b1, err := mm.Serialize()
- if err != nil {
- t.Fatal(err)
- }
- b.Write(b1)
- }
- t.Logf("wrote %d serialized MRT keepalives in the buffer", numwrite)
- r := bytes.NewReader(b.Bytes())
- scanner := bufio.NewScanner(r)
- scanner.Split(SplitMrt)
- for scanner.Scan() {
- numread += 1
- }
- t.Logf("scanner scanned %d serialized keepalives from the buffer", numread)
- assert.Equal(t, numwrite, numread)
-}