mirror of
https://github.com/osrg/gobgp.git
synced 2024-05-11 05:55:10 +00:00
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 <[email protected]>
This commit is contained in:
committed by
FUJITA Tomonori
parent
46b6fc2ccd
commit
d936841fb3
+81
-40
@@ -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 BMPTLV struct {
|
||||
Type uint16
|
||||
Length uint16
|
||||
Value []byte
|
||||
type BMPInfoTLVInterface interface {
|
||||
ParseValue([]byte) error
|
||||
Serialize() ([]byte, error)
|
||||
}
|
||||
|
||||
func NewBMPTLV(t uint16, v []byte) *BMPTLV {
|
||||
return &BMPTLV{
|
||||
Type: t,
|
||||
Length: uint16(len(v)),
|
||||
Value: v,
|
||||
type BMPInfoTLV struct {
|
||||
Type uint16
|
||||
Length uint16
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -604,6 +635,11 @@ func (body *BMPInitiation) Serialize() ([]byte, error) {
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
const (
|
||||
BMP_TERM_TLV_TYPE_STRING = iota
|
||||
BMP_TERM_TLV_TYPE_REASON
|
||||
)
|
||||
|
||||
const (
|
||||
BMP_TERM_REASON_ADMIN = iota
|
||||
BMP_TERM_REASON_UNSPEC
|
||||
@@ -650,6 +686,11 @@ func (body *BMPTermination) Serialize() ([]byte, error) {
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user