summaryrefslogtreecommitdiffhomepage
path: root/packet/bgp
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-04-12 09:39:09 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-04-12 09:39:09 +0900
commit9c3e5b159c6c9cc2f42302045006af721e33e2e9 (patch)
tree1162f97a33fd4dd67cd06f087bac29c81348d7b4 /packet/bgp
parent8daa5116576b3e3582e6c8e05ae1b64f56197ec6 (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.go20
-rw-r--r--packet/bgp/bgp_test.go147
-rw-r--r--packet/bgp/bmp.go609
-rw-r--r--packet/bgp/bmp_test.go73
-rw-r--r--packet/bgp/helper.go150
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)
+}