summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2017-05-22 15:00:28 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-05-23 14:34:55 +0900
commitd936841fb3238cc9ad0f728e1c929c8fad783290 (patch)
treed6084a79d938664e00d223139e7a061bf4efb03b
parent46b6fc2ccd02404f6fa3c5a4ea71fd192ee867ba (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.go115
-rw-r--r--packet/bmp/bmp_test.go6
-rw-r--r--server/bmp.go2
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
}