diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-04-11 09:09:50 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-03-31 14:28:04 +0900 |
commit | 6d401bedf5a947444a66daf5312719f6dba8b381 (patch) | |
tree | 3372759000a7347cc96004602fcad2d683ef7c39 /packet/bgp | |
parent | 59420a4c4623492085348e07fb78eaae51182782 (diff) |
packet: create mrt package
move mrt stuff from bgp to mrt package.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'packet/bgp')
-rw-r--r-- | packet/bgp/mrt.go | 798 | ||||
-rw-r--r-- | packet/bgp/mrt_test.go | 220 |
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) -} |