diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-04-12 09:39:09 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2016-04-12 09:39:09 +0900 |
commit | 9c3e5b159c6c9cc2f42302045006af721e33e2e9 (patch) | |
tree | 1162f97a33fd4dd67cd06f087bac29c81348d7b4 /packet/bgp | |
parent | 8daa5116576b3e3582e6c8e05ae1b64f56197ec6 (diff) |
packet: create bmp package
move bmp stuff from bgp to bmp package.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'packet/bgp')
-rw-r--r-- | packet/bgp/bgp.go | 20 | ||||
-rw-r--r-- | packet/bgp/bgp_test.go | 147 | ||||
-rw-r--r-- | packet/bgp/bmp.go | 609 | ||||
-rw-r--r-- | packet/bgp/bmp_test.go | 73 | ||||
-rw-r--r-- | packet/bgp/helper.go | 150 |
5 files changed, 186 insertions, 813 deletions
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index 2de2af63..8bfea717 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -6785,3 +6785,23 @@ func (msg *BGPMessage) Serialize() ([]byte, error) { } return append(h, b...), nil } + +type MessageError struct { + TypeCode uint8 + SubTypeCode uint8 + Data []byte + Message string +} + +func NewMessageError(typeCode, subTypeCode uint8, data []byte, msg string) error { + return &MessageError{ + TypeCode: typeCode, + SubTypeCode: subTypeCode, + Data: data, + Message: msg, + } +} + +func (e *MessageError) Error() string { + return e.Message +} diff --git a/packet/bgp/bgp_test.go b/packet/bgp/bgp_test.go index 29aa4e69..612e8c7b 100644 --- a/packet/bgp/bgp_test.go +++ b/packet/bgp/bgp_test.go @@ -1,3 +1,18 @@ +// Copyright (C) 2016 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 ( @@ -22,138 +37,8 @@ func refresh() *BGPMessage { return NewBGPRouteRefreshMessage(1, 2, 10) } -func open() *BGPMessage { - p1 := NewOptionParameterCapability( - []ParameterCapabilityInterface{NewCapRouteRefresh()}) - p2 := NewOptionParameterCapability( - []ParameterCapabilityInterface{NewCapMultiProtocol(RF_IPv4_UC)}) - g := &CapGracefulRestartTuple{4, 2, 3} - p3 := NewOptionParameterCapability( - []ParameterCapabilityInterface{NewCapGracefulRestart(false, 100, - []*CapGracefulRestartTuple{g})}) - p4 := NewOptionParameterCapability( - []ParameterCapabilityInterface{NewCapFourOctetASNumber(100000)}) - p5 := NewOptionParameterCapability( - []ParameterCapabilityInterface{NewCapAddPath(RF_IPv4_UC, BGP_ADD_PATH_BOTH)}) - return NewBGPOpenMessage(11033, 303, "100.4.10.3", - []OptionParameterInterface{p1, p2, p3, p4, p5}) -} - -func update() *BGPMessage { - w1 := NewIPAddrPrefix(23, "121.1.3.2") - w2 := NewIPAddrPrefix(17, "100.33.3.0") - w := []*IPAddrPrefix{w1, w2} - - aspath1 := []AsPathParamInterface{ - NewAsPathParam(2, []uint16{1000}), - NewAsPathParam(1, []uint16{1001, 1002}), - NewAsPathParam(2, []uint16{1003, 1004}), - } - - aspath2 := []AsPathParamInterface{ - NewAs4PathParam(2, []uint32{1000000}), - NewAs4PathParam(1, []uint32{1000001, 1002}), - NewAs4PathParam(2, []uint32{1003, 100004}), - } - - aspath3 := []*As4PathParam{ - NewAs4PathParam(2, []uint32{1000000}), - NewAs4PathParam(1, []uint32{1000001, 1002}), - NewAs4PathParam(2, []uint32{1003, 100004}), - } - - isTransitive := true - - ecommunities := []ExtendedCommunityInterface{ - NewTwoOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, 10003, 3<<20, isTransitive), - NewFourOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, 1<<20, 300, isTransitive), - NewIPv4AddressSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, "192.2.1.2", 3000, isTransitive), - &OpaqueExtended{ - Value: &DefaultOpaqueExtendedValue{[]byte{255, 1, 2, 3, 4, 5, 6, 7}}, - }, - &OpaqueExtended{ - Value: &ValidationExtended{Value: VALIDATION_STATE_INVALID}, - }, - &UnknownExtended{Type: 99, Value: []byte{0, 1, 2, 3, 4, 5, 6, 7}}, - NewESILabelExtended(1000, true), - NewESImportRouteTarget("11:22:33:44:55:66"), - NewMacMobilityExtended(123, false), - } - - mp_nlri := []AddrPrefixInterface{ - NewLabeledVPNIPAddrPrefix(20, "192.0.9.0", *NewMPLSLabelStack(1, 2, 3), - NewRouteDistinguisherTwoOctetAS(256, 10000)), - NewLabeledVPNIPAddrPrefix(26, "192.10.8.192", *NewMPLSLabelStack(5, 6, 7, 8), - NewRouteDistinguisherIPAddressAS("10.0.1.1", 10001)), - } - - mp_nlri2 := []AddrPrefixInterface{NewIPv6AddrPrefix(100, - "fe80:1234:1234:5667:8967:af12:8912:1023")} - - mp_nlri3 := []AddrPrefixInterface{NewLabeledVPNIPv6AddrPrefix(100, - "fe80:1234:1234:5667:8967:af12:1203:33a1", *NewMPLSLabelStack(5, 6), - NewRouteDistinguisherFourOctetAS(5, 6))} - - mp_nlri4 := []AddrPrefixInterface{NewLabeledIPAddrPrefix(25, "192.168.0.0", - *NewMPLSLabelStack(5, 6, 7))} - - mac, _ := net.ParseMAC("01:23:45:67:89:ab") - mp_nlri5 := []AddrPrefixInterface{ - NewEVPNNLRI(EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY, 0, - &EVPNEthernetAutoDiscoveryRoute{NewRouteDistinguisherFourOctetAS(5, 6), - EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, 2, 2}), - NewEVPNNLRI(EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT, 0, - &EVPNMacIPAdvertisementRoute{NewRouteDistinguisherFourOctetAS(5, 6), - EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, 3, 48, - mac, 32, net.ParseIP("192.2.1.2"), - []uint32{3, 4}}), - NewEVPNNLRI(EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG, 0, - &EVPNMulticastEthernetTagRoute{NewRouteDistinguisherFourOctetAS(5, 6), 3, 32, net.ParseIP("192.2.1.2")}), - NewEVPNNLRI(EVPN_ETHERNET_SEGMENT_ROUTE, 0, - &EVPNEthernetSegmentRoute{NewRouteDistinguisherFourOctetAS(5, 6), - EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, - 32, net.ParseIP("192.2.1.1")}), - } - - p := []PathAttributeInterface{ - NewPathAttributeOrigin(3), - NewPathAttributeAsPath(aspath1), - NewPathAttributeAsPath(aspath2), - NewPathAttributeNextHop("129.1.1.2"), - NewPathAttributeMultiExitDisc(1 << 20), - NewPathAttributeLocalPref(1 << 22), - NewPathAttributeAtomicAggregate(), - NewPathAttributeAggregator(uint16(30002), "129.0.2.99"), - NewPathAttributeAggregator(uint32(30002), "129.0.2.99"), - NewPathAttributeAggregator(uint32(300020), "129.0.2.99"), - NewPathAttributeCommunities([]uint32{1, 3}), - NewPathAttributeOriginatorId("10.10.0.1"), - NewPathAttributeClusterList([]string{"10.10.0.2", "10.10.0.3"}), - NewPathAttributeExtendedCommunities(ecommunities), - NewPathAttributeAs4Path(aspath3), - NewPathAttributeAs4Aggregator(10000, "112.22.2.1"), - NewPathAttributeMpReachNLRI("112.22.2.0", mp_nlri), - NewPathAttributeMpReachNLRI("1023::", mp_nlri2), - NewPathAttributeMpReachNLRI("fe80::", mp_nlri3), - NewPathAttributeMpReachNLRI("129.1.1.1", mp_nlri4), - NewPathAttributeMpReachNLRI("129.1.1.1", mp_nlri5), - NewPathAttributeMpUnreachNLRI(mp_nlri), - //NewPathAttributeMpReachNLRI("112.22.2.0", []AddrPrefixInterface{}), - //NewPathAttributeMpUnreachNLRI([]AddrPrefixInterface{}), - &PathAttributeUnknown{ - PathAttribute: PathAttribute{ - Flags: BGP_ATTR_FLAG_TRANSITIVE, - Type: 100, - Value: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, - }, - }, - } - n := []*IPAddrPrefix{NewIPAddrPrefix(24, "13.2.3.1")} - return NewBGPUpdateMessage(w, p, n) -} - func Test_Message(t *testing.T) { - l := []*BGPMessage{keepalive(), notification(), refresh(), open(), update()} + l := []*BGPMessage{keepalive(), notification(), refresh(), NewTestBGPOpenMessage(), NewTestBGPUpdateMessage()} for _, m1 := range l { buf1, _ := m1.Serialize() t.Log("LEN =", len(buf1)) diff --git a/packet/bgp/bmp.go b/packet/bgp/bmp.go deleted file mode 100644 index 4813aff9..00000000 --- a/packet/bgp/bmp.go +++ /dev/null @@ -1,609 +0,0 @@ -// Copyright (C) 2014,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 ( - "encoding/binary" - "fmt" - "math" - "net" -) - -type BMPHeader struct { - Version uint8 - Length uint32 - Type uint8 -} - -const ( - BMP_VERSION = 3 - BMP_HEADER_SIZE = 6 - BMP_PEER_HEADER_SIZE = 42 -) - -const ( - BMP_DEFAULT_PORT = 11019 -) - -const ( - BMP_PEER_TYPE_GLOBAL uint8 = iota - BMP_PEER_TYPE_L3VPN -) - -func (h *BMPHeader) DecodeFromBytes(data []byte) error { - h.Version = data[0] - if data[0] != BMP_VERSION { - return fmt.Errorf("error version") - } - h.Length = binary.BigEndian.Uint32(data[1:5]) - h.Type = data[5] - return nil -} - -func (h *BMPHeader) Serialize() ([]byte, error) { - buf := make([]byte, BMP_HEADER_SIZE) - buf[0] = h.Version - binary.BigEndian.PutUint32(buf[1:], h.Length) - buf[5] = h.Type - return buf, nil -} - -type BMPPeerHeader struct { - PeerType uint8 - IsPostPolicy bool - PeerDistinguisher uint64 - PeerAddress net.IP - PeerAS uint32 - PeerBGPID net.IP - Timestamp float64 - Flags uint8 -} - -func NewBMPPeerHeader(t uint8, policy bool, dist uint64, address string, as uint32, id string, stamp float64) *BMPPeerHeader { - h := &BMPPeerHeader{ - PeerType: t, - IsPostPolicy: policy, - PeerDistinguisher: dist, - PeerAS: as, - PeerBGPID: net.ParseIP(id).To4(), - Timestamp: stamp, - } - if policy == true { - h.Flags |= (1 << 6) - } - if net.ParseIP(address).To4() != nil { - h.PeerAddress = net.ParseIP(address).To4() - } else { - h.PeerAddress = net.ParseIP(address).To16() - h.Flags |= (1 << 7) - } - return h -} - -func (h *BMPPeerHeader) DecodeFromBytes(data []byte) error { - h.PeerType = data[0] - h.Flags = data[1] - if h.Flags&(1<<6) != 0 { - h.IsPostPolicy = true - } else { - h.IsPostPolicy = false - } - h.PeerDistinguisher = binary.BigEndian.Uint64(data[2:10]) - if h.Flags&(1<<7) != 0 { - h.PeerAddress = net.IP(data[10:26]).To16() - } else { - h.PeerAddress = net.IP(data[22:26]).To4() - } - h.PeerAS = binary.BigEndian.Uint32(data[26:30]) - h.PeerBGPID = data[30:34] - - timestamp1 := binary.BigEndian.Uint32(data[34:38]) - timestamp2 := binary.BigEndian.Uint32(data[38:42]) - h.Timestamp = float64(timestamp1) + float64(timestamp2)*math.Pow10(-6) - return nil -} - -func (h *BMPPeerHeader) Serialize() ([]byte, error) { - buf := make([]byte, BMP_PEER_HEADER_SIZE) - buf[0] = h.PeerType - buf[1] = h.Flags - binary.BigEndian.PutUint64(buf[2:10], h.PeerDistinguisher) - if h.Flags&(1<<7) != 0 { - copy(buf[10:26], h.PeerAddress) - } else { - copy(buf[22:26], h.PeerAddress.To4()) - } - binary.BigEndian.PutUint32(buf[26:30], h.PeerAS) - copy(buf[30:34], h.PeerBGPID) - t1, t2 := math.Modf(h.Timestamp) - t2 = math.Ceil(t2 * math.Pow10(6)) - binary.BigEndian.PutUint32(buf[34:38], uint32(t1)) - binary.BigEndian.PutUint32(buf[38:42], uint32(t2)) - return buf, nil -} - -type BMPRouteMonitoring struct { - BGPUpdate *BGPMessage - BGPUpdatePayload []byte -} - -func NewBMPRouteMonitoring(p BMPPeerHeader, update *BGPMessage) *BMPMessage { - return &BMPMessage{ - Header: BMPHeader{ - Version: BMP_VERSION, - Type: BMP_MSG_ROUTE_MONITORING, - }, - PeerHeader: p, - Body: &BMPRouteMonitoring{ - BGPUpdate: update, - }, - } -} - -func (body *BMPRouteMonitoring) ParseBody(msg *BMPMessage, data []byte) error { - update, err := ParseBGPMessage(data) - if err != nil { - return err - } - body.BGPUpdate = update - return nil -} - -func (body *BMPRouteMonitoring) Serialize() ([]byte, error) { - if body.BGPUpdatePayload != nil { - return body.BGPUpdatePayload, nil - } - return body.BGPUpdate.Serialize() -} - -const ( - BMP_STAT_TYPE_REJECTED = iota - BMP_STAT_TYPE_DUPLICATE_PREFIX - BMP_STAT_TYPE_DUPLICATE_WITHDRAW - BMP_STAT_TYPE_INV_UPDATE_DUE_TO_CLUSTER_LIST_LOOP - BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_PATH_LOOP - BMP_STAT_TYPE_INV_UPDATE_DUE_TO_ORIGINATOR_ID - BMP_STAT_TYPE_INV_UPDATE_DUE_TO_AS_CONFED_LOOP - BMP_STAT_TYPE_ADJ_RIB_IN - BMP_STAT_TYPE_LOC_RIB -) - -type BMPStatsTLV struct { - Type uint16 - Length uint16 - Value uint64 -} - -type BMPStatisticsReport struct { - Count uint32 - Stats []BMPStatsTLV -} - -const ( - BMP_PEER_DOWN_REASON_UNKNOWN = iota - BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION - BMP_PEER_DOWN_REASON_LOCAL_NO_NOTIFICATION - BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION - BMP_PEER_DOWN_REASON_REMOTE_NO_NOTIFICATION -) - -type BMPPeerDownNotification struct { - Reason uint8 - BGPNotification *BGPMessage - Data []byte -} - -func NewBMPPeerDownNotification(p BMPPeerHeader, reason uint8, notification *BGPMessage, data []byte) *BMPMessage { - b := &BMPPeerDownNotification{ - Reason: reason, - } - switch reason { - case BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION: - b.BGPNotification = notification - default: - b.Data = data - } - return &BMPMessage{ - Header: BMPHeader{ - Version: BMP_VERSION, - Type: BMP_MSG_PEER_DOWN_NOTIFICATION, - }, - PeerHeader: p, - Body: b, - } -} - -func (body *BMPPeerDownNotification) ParseBody(msg *BMPMessage, data []byte) error { - body.Reason = data[0] - data = data[1:] - if body.Reason == BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION || body.Reason == BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION { - notification, err := ParseBGPMessage(data) - if err != nil { - return err - } - body.BGPNotification = notification - } else { - body.Data = data - } - return nil -} - -func (body *BMPPeerDownNotification) Serialize() ([]byte, error) { - buf := make([]byte, 1) - buf[0] = body.Reason - switch body.Reason { - case BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION, BMP_PEER_DOWN_REASON_REMOTE_BGP_NOTIFICATION: - if body.BGPNotification != nil { - b, err := body.BGPNotification.Serialize() - if err != nil { - return nil, err - } else { - buf = append(buf, b...) - } - } - default: - if body.Data != nil { - buf = append(buf, body.Data...) - } - } - return buf, nil -} - -type BMPPeerUpNotification struct { - LocalAddress net.IP - LocalPort uint16 - RemotePort uint16 - SentOpenMsg *BGPMessage - ReceivedOpenMsg *BGPMessage -} - -func NewBMPPeerUpNotification(p BMPPeerHeader, lAddr string, lPort, rPort uint16, sent, recv *BGPMessage) *BMPMessage { - b := &BMPPeerUpNotification{ - LocalPort: lPort, - RemotePort: rPort, - SentOpenMsg: sent, - ReceivedOpenMsg: recv, - } - addr := net.ParseIP(lAddr) - if addr.To4() != nil { - b.LocalAddress = addr.To4() - } else { - b.LocalAddress = addr.To16() - } - return &BMPMessage{ - Header: BMPHeader{ - Version: BMP_VERSION, - Type: BMP_MSG_PEER_UP_NOTIFICATION, - }, - PeerHeader: p, - Body: b, - } -} - -func (body *BMPPeerUpNotification) ParseBody(msg *BMPMessage, data []byte) error { - if msg.PeerHeader.Flags&(1<<7) != 0 { - body.LocalAddress = net.IP(data[:16]).To16() - } else { - body.LocalAddress = net.IP(data[12:16]).To4() - } - - body.LocalPort = binary.BigEndian.Uint16(data[16:18]) - body.RemotePort = binary.BigEndian.Uint16(data[18:20]) - - data = data[20:] - sentopen, err := ParseBGPMessage(data) - if err != nil { - return err - } - body.SentOpenMsg = sentopen - data = data[body.SentOpenMsg.Header.Len:] - body.ReceivedOpenMsg, err = ParseBGPMessage(data) - if err != nil { - return err - } - return nil -} - -func (body *BMPPeerUpNotification) Serialize() ([]byte, error) { - buf := make([]byte, 20) - if body.LocalAddress.To4() != nil { - copy(buf[12:16], body.LocalAddress.To4()) - } else { - copy(buf[:16], body.LocalAddress.To16()) - } - - binary.BigEndian.PutUint16(buf[16:18], body.LocalPort) - binary.BigEndian.PutUint16(buf[18:20], body.RemotePort) - - m, _ := body.SentOpenMsg.Serialize() - buf = append(buf, m...) - m, _ = body.ReceivedOpenMsg.Serialize() - buf = append(buf, m...) - return buf, nil -} - -func (body *BMPStatisticsReport) ParseBody(msg *BMPMessage, data []byte) error { - body.Count = binary.BigEndian.Uint32(data[0:4]) - data = data[4:] - for len(data) >= 4 { - s := BMPStatsTLV{} - s.Type = binary.BigEndian.Uint16(data[0:2]) - s.Length = binary.BigEndian.Uint16(data[2:4]) - data = data[4:] - if len(data) < int(s.Length) { - break - } - if s.Type == BMP_STAT_TYPE_ADJ_RIB_IN || s.Type == BMP_STAT_TYPE_LOC_RIB { - if s.Length < 8 { - break - } - s.Value = binary.BigEndian.Uint64(data[:8]) - } else { - if s.Length < 4 { - break - } - s.Value = uint64(binary.BigEndian.Uint32(data[:4])) - } - body.Stats = append(body.Stats, s) - data = data[s.Length:] - } - return nil -} - -func (body *BMPStatisticsReport) Serialize() ([]byte, error) { - // TODO - buf := make([]byte, 4) - body.Count = uint32(len(body.Stats)) - binary.BigEndian.PutUint32(buf[0:4], body.Count) - - return buf, nil -} - -type BMPTLV struct { - Type uint16 - Length uint16 - Value []byte -} - -func NewBMPTLV(t uint16, v []byte) *BMPTLV { - return &BMPTLV{ - Type: t, - Length: uint16(len(v)), - Value: v, - } -} - -func (tlv *BMPTLV) DecodeFromBytes(data []byte) error { - //TODO: check data length - tlv.Type = binary.BigEndian.Uint16(data[0:2]) - tlv.Length = binary.BigEndian.Uint16(data[2:4]) - tlv.Value = data[4 : 4+tlv.Length] - return nil -} - -func (tlv *BMPTLV) Serialize() ([]byte, error) { - if tlv.Length == 0 { - tlv.Length = uint16(len(tlv.Value)) - } - buf := make([]byte, 4+tlv.Length) - binary.BigEndian.PutUint16(buf[0:2], tlv.Type) - binary.BigEndian.PutUint16(buf[2:4], tlv.Length) - copy(buf[4:], tlv.Value) - return buf, nil -} - -func (tlv *BMPTLV) Len() int { - return 4 + int(tlv.Length) -} - -type BMPInitiation struct { - Info []BMPTLV -} - -func NewBMPInitiation(info []BMPTLV) *BMPMessage { - return &BMPMessage{ - Header: BMPHeader{ - Version: BMP_VERSION, - Type: BMP_MSG_INITIATION, - }, - Body: &BMPInitiation{ - Info: info, - }, - } -} - -func (body *BMPInitiation) ParseBody(msg *BMPMessage, data []byte) error { - for len(data) > 0 { - tlv := BMPTLV{} - tlv.DecodeFromBytes(data) - body.Info = append(body.Info, tlv) - data = data[tlv.Len():] - } - return nil -} - -func (body *BMPInitiation) Serialize() ([]byte, error) { - buf := make([]byte, 0) - for _, tlv := range body.Info { - b, err := tlv.Serialize() - if err != nil { - return buf, err - } - buf = append(buf, b...) - } - return buf, nil -} - -type BMPTermination struct { - Info []BMPTLV -} - -func NewBMPTermination(info []BMPTLV) *BMPMessage { - return &BMPMessage{ - Header: BMPHeader{ - Version: BMP_VERSION, - Type: BMP_MSG_TERMINATION, - }, - Body: &BMPTermination{ - Info: info, - }, - } -} - -func (body *BMPTermination) ParseBody(msg *BMPMessage, data []byte) error { - for len(data) > 0 { - tlv := BMPTLV{} - tlv.DecodeFromBytes(data) - body.Info = append(body.Info, tlv) - data = data[tlv.Len():] - } - return nil -} - -func (body *BMPTermination) Serialize() ([]byte, error) { - buf := make([]byte, 0) - for _, tlv := range body.Info { - b, err := tlv.Serialize() - if err != nil { - return buf, err - } - buf = append(buf, b...) - } - return buf, nil -} - -type BMPBody interface { - // Sigh, some body messages need a BMPHeader to parse the body - // data so we need to pass BMPHeader (avoid DecodeFromBytes - // function name). - ParseBody(*BMPMessage, []byte) error - Serialize() ([]byte, error) -} - -type BMPMessage struct { - Header BMPHeader - PeerHeader BMPPeerHeader - Body BMPBody -} - -func (msg *BMPMessage) Serialize() ([]byte, error) { - buf := make([]byte, 0) - if msg.Header.Type != BMP_MSG_INITIATION { - p, err := msg.PeerHeader.Serialize() - if err != nil { - return nil, err - } - buf = append(buf, p...) - } - - b, err := msg.Body.Serialize() - if err != nil { - return nil, err - } - buf = append(buf, b...) - - if msg.Header.Length == 0 { - msg.Header.Length = uint32(BMP_HEADER_SIZE + len(buf)) - } - - h, err := msg.Header.Serialize() - if err != nil { - return nil, err - } - return append(h, buf...), nil -} - -func (msg *BMPMessage) Len() int { - return int(msg.Header.Length) -} - -const ( - BMP_MSG_ROUTE_MONITORING = iota - BMP_MSG_STATISTICS_REPORT - BMP_MSG_PEER_DOWN_NOTIFICATION - BMP_MSG_PEER_UP_NOTIFICATION - BMP_MSG_INITIATION - BMP_MSG_TERMINATION -) - -func ParseBMPMessage(data []byte) (*BMPMessage, error) { - msg := &BMPMessage{} - err := msg.Header.DecodeFromBytes(data) - if err != nil { - return nil, err - } - data = data[BMP_HEADER_SIZE:msg.Header.Length] - - switch msg.Header.Type { - case BMP_MSG_ROUTE_MONITORING: - msg.Body = &BMPRouteMonitoring{} - case BMP_MSG_STATISTICS_REPORT: - msg.Body = &BMPStatisticsReport{} - case BMP_MSG_PEER_DOWN_NOTIFICATION: - msg.Body = &BMPPeerDownNotification{} - case BMP_MSG_PEER_UP_NOTIFICATION: - msg.Body = &BMPPeerUpNotification{} - case BMP_MSG_INITIATION: - msg.Body = &BMPInitiation{} - case BMP_MSG_TERMINATION: - msg.Body = &BMPTermination{} - } - - if msg.Header.Type != BMP_MSG_INITIATION { - msg.PeerHeader.DecodeFromBytes(data) - data = data[BMP_PEER_HEADER_SIZE:] - } - - err = msg.Body.ParseBody(msg, data) - if err != nil { - return nil, err - } - return msg, nil -} - -type MessageError struct { - TypeCode uint8 - SubTypeCode uint8 - Data []byte - Message string -} - -func NewMessageError(typeCode, subTypeCode uint8, data []byte, msg string) error { - return &MessageError{ - TypeCode: typeCode, - SubTypeCode: subTypeCode, - Data: data, - Message: msg, - } -} - -func (e *MessageError) Error() string { - return e.Message -} - -func SplitBMP(data []byte, atEOF bool) (advance int, token []byte, err error) { - if atEOF && len(data) == 0 || len(data) < BMP_HEADER_SIZE { - return 0, nil, nil - } - - msg := &BMPMessage{} - msg.Header.DecodeFromBytes(data) - if uint32(len(data)) < msg.Header.Length { - return 0, nil, nil - } - - return int(msg.Header.Length), data[0:msg.Header.Length], nil -} diff --git a/packet/bgp/bmp_test.go b/packet/bgp/bmp_test.go deleted file mode 100644 index e07c2455..00000000 --- a/packet/bgp/bmp_test.go +++ /dev/null @@ -1,73 +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 ( - "github.com/stretchr/testify/assert" - "reflect" - "testing" -) - -func verify(t *testing.T, m1 *BMPMessage) { - buf1, _ := m1.Serialize() - m2, err := ParseBMPMessage(buf1) - if err != nil { - t.Error(err) - } - buf2, _ := m2.Serialize() - - if reflect.DeepEqual(m1, m2) == true { - t.Log("OK") - } else { - t.Error("Something wrong") - t.Error(len(buf1), m1, buf1) - t.Error(len(buf2), m2, buf2) - } -} - -func Test_Initiation(t *testing.T) { - verify(t, NewBMPInitiation(nil)) - tlv := NewBMPTLV(1, []byte{0x3, 0xb, 0x0, 0x0, 0x0, 0xf, 0x42, 0x40}) - m := NewBMPInitiation([]BMPTLV{*tlv}) - verify(t, m) -} - -func Test_PeerUpNotification(t *testing.T) { - m := open() - p0 := NewBMPPeerHeader(0, false, 1000, "10.0.0.1", 70000, "10.0.0.2", 1) - verify(t, NewBMPPeerUpNotification(*p0, "10.0.0.3", 10, 100, m, m)) - p1 := NewBMPPeerHeader(0, false, 1000, "fe80::6e40:8ff:feab:2c2a", 70000, "10.0.0.2", 1) - verify(t, NewBMPPeerUpNotification(*p1, "fe80::6e40:8ff:feab:2c2a", 10, 100, m, m)) -} - -func Test_PeerDownNotification(t *testing.T) { - p0 := NewBMPPeerHeader(0, false, 1000, "10.0.0.1", 70000, "10.0.0.2", 1) - verify(t, NewBMPPeerDownNotification(*p0, BMP_PEER_DOWN_REASON_UNKNOWN, nil, []byte{0x3, 0xb})) - m := NewBGPNotificationMessage(1, 2, nil) - verify(t, NewBMPPeerDownNotification(*p0, BMP_PEER_DOWN_REASON_LOCAL_BGP_NOTIFICATION, m, nil)) -} - -func Test_RouteMonitoring(t *testing.T) { - m := update() - p0 := NewBMPPeerHeader(0, false, 1000, "fe80::6e40:8ff:feab:2c2a", 70000, "10.0.0.2", 1) - verify(t, NewBMPRouteMonitoring(*p0, m)) -} - -func Test_BogusHeader(t *testing.T) { - h, err := ParseBMPMessage(make([]byte, 10)) - assert.Nil(t, h) - assert.NotNil(t, err) -} diff --git a/packet/bgp/helper.go b/packet/bgp/helper.go new file mode 100644 index 00000000..423361b1 --- /dev/null +++ b/packet/bgp/helper.go @@ -0,0 +1,150 @@ +// Copyright (C) 2016 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 ( + "net" +) + +func NewTestBGPOpenMessage() *BGPMessage { + p1 := NewOptionParameterCapability( + []ParameterCapabilityInterface{NewCapRouteRefresh()}) + p2 := NewOptionParameterCapability( + []ParameterCapabilityInterface{NewCapMultiProtocol(RF_IPv4_UC)}) + g := &CapGracefulRestartTuple{4, 2, 3} + p3 := NewOptionParameterCapability( + []ParameterCapabilityInterface{NewCapGracefulRestart(false, 100, + []*CapGracefulRestartTuple{g})}) + p4 := NewOptionParameterCapability( + []ParameterCapabilityInterface{NewCapFourOctetASNumber(100000)}) + p5 := NewOptionParameterCapability( + []ParameterCapabilityInterface{NewCapAddPath(RF_IPv4_UC, BGP_ADD_PATH_BOTH)}) + return NewBGPOpenMessage(11033, 303, "100.4.10.3", + []OptionParameterInterface{p1, p2, p3, p4, p5}) +} + +func NewTestBGPUpdateMessage() *BGPMessage { + w1 := NewIPAddrPrefix(23, "121.1.3.2") + w2 := NewIPAddrPrefix(17, "100.33.3.0") + w := []*IPAddrPrefix{w1, w2} + + aspath1 := []AsPathParamInterface{ + NewAsPathParam(2, []uint16{1000}), + NewAsPathParam(1, []uint16{1001, 1002}), + NewAsPathParam(2, []uint16{1003, 1004}), + } + + aspath2 := []AsPathParamInterface{ + NewAs4PathParam(2, []uint32{1000000}), + NewAs4PathParam(1, []uint32{1000001, 1002}), + NewAs4PathParam(2, []uint32{1003, 100004}), + } + + aspath3 := []*As4PathParam{ + NewAs4PathParam(2, []uint32{1000000}), + NewAs4PathParam(1, []uint32{1000001, 1002}), + NewAs4PathParam(2, []uint32{1003, 100004}), + } + + isTransitive := true + + ecommunities := []ExtendedCommunityInterface{ + NewTwoOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, 10003, 3<<20, isTransitive), + NewFourOctetAsSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, 1<<20, 300, isTransitive), + NewIPv4AddressSpecificExtended(EC_SUBTYPE_ROUTE_TARGET, "192.2.1.2", 3000, isTransitive), + &OpaqueExtended{ + Value: &DefaultOpaqueExtendedValue{[]byte{255, 1, 2, 3, 4, 5, 6, 7}}, + }, + &OpaqueExtended{ + Value: &ValidationExtended{Value: VALIDATION_STATE_INVALID}, + }, + &UnknownExtended{Type: 99, Value: []byte{0, 1, 2, 3, 4, 5, 6, 7}}, + NewESILabelExtended(1000, true), + NewESImportRouteTarget("11:22:33:44:55:66"), + NewMacMobilityExtended(123, false), + } + + mp_nlri := []AddrPrefixInterface{ + NewLabeledVPNIPAddrPrefix(20, "192.0.9.0", *NewMPLSLabelStack(1, 2, 3), + NewRouteDistinguisherTwoOctetAS(256, 10000)), + NewLabeledVPNIPAddrPrefix(26, "192.10.8.192", *NewMPLSLabelStack(5, 6, 7, 8), + NewRouteDistinguisherIPAddressAS("10.0.1.1", 10001)), + } + + mp_nlri2 := []AddrPrefixInterface{NewIPv6AddrPrefix(100, + "fe80:1234:1234:5667:8967:af12:8912:1023")} + + mp_nlri3 := []AddrPrefixInterface{NewLabeledVPNIPv6AddrPrefix(100, + "fe80:1234:1234:5667:8967:af12:1203:33a1", *NewMPLSLabelStack(5, 6), + NewRouteDistinguisherFourOctetAS(5, 6))} + + mp_nlri4 := []AddrPrefixInterface{NewLabeledIPAddrPrefix(25, "192.168.0.0", + *NewMPLSLabelStack(5, 6, 7))} + + mac, _ := net.ParseMAC("01:23:45:67:89:ab") + mp_nlri5 := []AddrPrefixInterface{ + NewEVPNNLRI(EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY, 0, + &EVPNEthernetAutoDiscoveryRoute{NewRouteDistinguisherFourOctetAS(5, 6), + EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, 2, 2}), + NewEVPNNLRI(EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT, 0, + &EVPNMacIPAdvertisementRoute{NewRouteDistinguisherFourOctetAS(5, 6), + EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, 3, 48, + mac, 32, net.ParseIP("192.2.1.2"), + []uint32{3, 4}}), + NewEVPNNLRI(EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG, 0, + &EVPNMulticastEthernetTagRoute{NewRouteDistinguisherFourOctetAS(5, 6), 3, 32, net.ParseIP("192.2.1.2")}), + NewEVPNNLRI(EVPN_ETHERNET_SEGMENT_ROUTE, 0, + &EVPNEthernetSegmentRoute{NewRouteDistinguisherFourOctetAS(5, 6), + EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, + 32, net.ParseIP("192.2.1.1")}), + } + + p := []PathAttributeInterface{ + NewPathAttributeOrigin(3), + NewPathAttributeAsPath(aspath1), + NewPathAttributeAsPath(aspath2), + NewPathAttributeNextHop("129.1.1.2"), + NewPathAttributeMultiExitDisc(1 << 20), + NewPathAttributeLocalPref(1 << 22), + NewPathAttributeAtomicAggregate(), + NewPathAttributeAggregator(uint16(30002), "129.0.2.99"), + NewPathAttributeAggregator(uint32(30002), "129.0.2.99"), + NewPathAttributeAggregator(uint32(300020), "129.0.2.99"), + NewPathAttributeCommunities([]uint32{1, 3}), + NewPathAttributeOriginatorId("10.10.0.1"), + NewPathAttributeClusterList([]string{"10.10.0.2", "10.10.0.3"}), + NewPathAttributeExtendedCommunities(ecommunities), + NewPathAttributeAs4Path(aspath3), + NewPathAttributeAs4Aggregator(10000, "112.22.2.1"), + NewPathAttributeMpReachNLRI("112.22.2.0", mp_nlri), + NewPathAttributeMpReachNLRI("1023::", mp_nlri2), + NewPathAttributeMpReachNLRI("fe80::", mp_nlri3), + NewPathAttributeMpReachNLRI("129.1.1.1", mp_nlri4), + NewPathAttributeMpReachNLRI("129.1.1.1", mp_nlri5), + NewPathAttributeMpUnreachNLRI(mp_nlri), + //NewPathAttributeMpReachNLRI("112.22.2.0", []AddrPrefixInterface{}), + //NewPathAttributeMpUnreachNLRI([]AddrPrefixInterface{}), + &PathAttributeUnknown{ + PathAttribute: PathAttribute{ + Flags: BGP_ATTR_FLAG_TRANSITIVE, + Type: 100, + Value: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, + }, + }, + } + n := []*IPAddrPrefix{NewIPAddrPrefix(24, "13.2.3.1")} + return NewBGPUpdateMessage(w, p, n) +} |