diff options
author | IWASE Yusuke <iwase.yusuke0@gmail.com> | 2017-05-22 15:00:28 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-05-23 14:34:55 +0900 |
commit | d936841fb3238cc9ad0f728e1c929c8fad783290 (patch) | |
tree | d6084a79d938664e00d223139e7a061bf4efb03b | |
parent | 46b6fc2ccd02404f6fa3c5a4ea71fd192ee867ba (diff) |
bmp: Implement Information TLV on Initiation message
Currently, the TLV fields are implemented as BMPTLV on the Initiation
messages, but not enough decoded and required to be constructed in
binary format.
This patch introduces BMPInfoTLV and makes easy to handle the TLV
fields.
Note: This patch obsoletes BMPTLV structure.
Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com>
-rw-r--r-- | packet/bmp/bmp.go | 115 | ||||
-rw-r--r-- | packet/bmp/bmp_test.go | 6 | ||||
-rw-r--r-- | server/bmp.go | 2 |
3 files changed, 83 insertions, 40 deletions
diff --git a/packet/bmp/bmp.go b/packet/bmp/bmp.go index ba517bda..e93ae61e 100644 --- a/packet/bmp/bmp.go +++ b/packet/bmp/bmp.go @@ -519,58 +519,73 @@ const ( BMP_INIT_TLV_TYPE_SYS_NAME ) -const ( - BMP_TERM_TLV_TYPE_STRING = iota - BMP_TERM_TLV_TYPE_REASON -) - -const ( - BMP_ROUTE_MIRRORING_TLV_TYPE_BGP_MSG = iota - BMP_ROUTE_MIRRORING_TLV_TYPE_INFO -) +type BMPInfoTLVInterface interface { + ParseValue([]byte) error + Serialize() ([]byte, error) +} -type BMPTLV struct { +type BMPInfoTLV struct { Type uint16 Length uint16 - Value []byte } -func NewBMPTLV(t uint16, v []byte) *BMPTLV { - return &BMPTLV{ - Type: t, - Length: uint16(len(v)), - Value: v, +type BMPInfoTLVString struct { + BMPInfoTLV + Value string +} + +func NewBMPInfoTLVString(t uint16, v string) *BMPInfoTLVString { + return &BMPInfoTLVString{ + BMPInfoTLV: BMPInfoTLV{Type: t}, + 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] +func (s *BMPInfoTLVString) ParseValue(data []byte) error { + s.Value = string(data[:s.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) +func (s *BMPInfoTLVString) Serialize() ([]byte, error) { + s.Length = uint16(len([]byte(s.Value))) + buf := make([]byte, 4) + binary.BigEndian.PutUint16(buf[0:2], s.Type) + binary.BigEndian.PutUint16(buf[2:4], s.Length) + buf = append(buf, []byte(s.Value)...) return buf, nil } -func (tlv *BMPTLV) Len() int { - return 4 + int(tlv.Length) +type BMPInfoTLVUnknown struct { + BMPInfoTLV + Value []byte +} + +func NewBMPInfoTLVUnknown(t uint16, v []byte) *BMPInfoTLVUnknown { + return &BMPInfoTLVUnknown{ + BMPInfoTLV: BMPInfoTLV{Type: t}, + Value: v, + } +} + +func (s *BMPInfoTLVUnknown) ParseValue(data []byte) error { + s.Value = data[:s.Length] + return nil +} + +func (s *BMPInfoTLVUnknown) Serialize() ([]byte, error) { + s.Length = uint16(len([]byte(s.Value))) + buf := make([]byte, 4) + binary.BigEndian.PutUint16(buf[0:2], s.Type) + binary.BigEndian.PutUint16(buf[2:4], s.Length) + buf = append(buf, s.Value...) + return buf, nil } type BMPInitiation struct { - Info []BMPTLV + Info []BMPInfoTLVInterface } -func NewBMPInitiation(info []BMPTLV) *BMPMessage { +func NewBMPInitiation(info []BMPInfoTLVInterface) *BMPMessage { return &BMPMessage{ Header: BMPHeader{ Version: BMP_VERSION, @@ -583,11 +598,27 @@ func NewBMPInitiation(info []BMPTLV) *BMPMessage { } func (body *BMPInitiation) ParseBody(msg *BMPMessage, data []byte) error { - for len(data) > 0 { - tlv := BMPTLV{} - tlv.DecodeFromBytes(data) + for len(data) >= 4 { + tl := BMPInfoTLV{ + Type: binary.BigEndian.Uint16(data[0:2]), + Length: binary.BigEndian.Uint16(data[2:4]), + } + data = data[4:] + if len(data) < int(tl.Length) { + return fmt.Errorf("value lengh is not enough: %d bytes (%d bytes expected)", len(data), tl.Length) + } + var tlv BMPInfoTLVInterface + switch tl.Type { + case BMP_INIT_TLV_TYPE_STRING, BMP_INIT_TLV_TYPE_SYS_DESCR, BMP_INIT_TLV_TYPE_SYS_NAME: + tlv = &BMPInfoTLVString{BMPInfoTLV: tl} + default: + tlv = &BMPInfoTLVUnknown{BMPInfoTLV: tl} + } + if err := tlv.ParseValue(data); err != nil { + return err + } body.Info = append(body.Info, tlv) - data = data[tlv.Len():] + data = data[tl.Length:] } return nil } @@ -605,6 +636,11 @@ func (body *BMPInitiation) Serialize() ([]byte, error) { } const ( + BMP_TERM_TLV_TYPE_STRING = iota + BMP_TERM_TLV_TYPE_REASON +) + +const ( BMP_TERM_REASON_ADMIN = iota BMP_TERM_REASON_UNSPEC BMP_TERM_REASON_OUT_OF_RESOURCES @@ -651,6 +687,11 @@ func (body *BMPTermination) Serialize() ([]byte, error) { } const ( + BMP_ROUTE_MIRRORING_TLV_TYPE_BGP_MSG = iota + BMP_ROUTE_MIRRORING_TLV_TYPE_INFO +) + +const ( BMP_ROUTE_MIRRORING_INFO_ERR_PDU = iota BMP_ROUTE_MIRRORING_INFO_MSG_LOST ) diff --git a/packet/bmp/bmp_test.go b/packet/bmp/bmp_test.go index 5e70710f..d2e07767 100644 --- a/packet/bmp/bmp_test.go +++ b/packet/bmp/bmp_test.go @@ -41,8 +41,10 @@ func verify(t *testing.T, m1 *BMPMessage) { 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}) + m := NewBMPInitiation([]BMPInfoTLVInterface{ + NewBMPInfoTLVString(BMP_INIT_TLV_TYPE_STRING, "free-form UTF-8 string"), + NewBMPInfoTLVUnknown(0xff, []byte{0x01, 0x02, 0x03, 0x04}), + }) verify(t, m) } diff --git a/server/bmp.go b/server/bmp.go index 1d97104f..ec2c26ee 100644 --- a/server/bmp.go +++ b/server/bmp.go @@ -148,7 +148,7 @@ func (b *bmpClient) loop() { return err } - if err := write(bmp.NewBMPInitiation([]bmp.BMPTLV{})); err != nil { + if err := write(bmp.NewBMPInitiation([]bmp.BMPInfoTLVInterface{})); err != nil { return false } |