-
Daniel Czerwonk authoredDaniel Czerwonk authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
update.go 3.58 KiB
package packet
import (
"bytes"
"fmt"
"github.com/taktv6/tflow2/convert"
)
type BGPUpdate struct {
WithdrawnRoutesLen uint16
WithdrawnRoutes *NLRI
TotalPathAttrLen uint16
PathAttributes *PathAttribute
NLRI *NLRI
}
// SerializeUpdate serializes an BGPUpdate to wire format
func (b *BGPUpdate) SerializeUpdate(opt *EncodeOptions) ([]byte, error) {
budget := MaxLen - MinLen
buf := bytes.NewBuffer(nil)
withdrawBuf := bytes.NewBuffer(nil)
for withdraw := b.WithdrawnRoutes; withdraw != nil; withdraw = withdraw.Next {
budget -= int(withdraw.serialize(withdrawBuf, opt.UseAddPath))
if budget < 0 {
return nil, fmt.Errorf("update too long")
}
}
pathAttributesBuf := bytes.NewBuffer(nil)
for pa := b.PathAttributes; pa != nil; pa = pa.Next {
paLen := int(pa.Serialize(pathAttributesBuf, opt))
budget -= paLen
if budget < 0 {
return nil, fmt.Errorf("update too long")
}
}
nlriBuf := bytes.NewBuffer(nil)
for nlri := b.NLRI; nlri != nil; nlri = nlri.Next {
budget -= int(nlri.serialize(nlriBuf, opt.UseAddPath))
if budget < 0 {
return nil, fmt.Errorf("update too long")
}
}
withdrawnRoutesLen := withdrawBuf.Len()
if withdrawnRoutesLen > 65535 {
return nil, fmt.Errorf("Invalid Withdrawn Routes Length: %d", withdrawnRoutesLen)
}
totalPathAttributesLen := pathAttributesBuf.Len()
if totalPathAttributesLen > 65535 {
return nil, fmt.Errorf("Invalid Total Path Attribute Length: %d", totalPathAttributesLen)
}
totalLength := 2 + withdrawnRoutesLen + totalPathAttributesLen + 2 + nlriBuf.Len() + 19
if totalLength > 4096 {
return nil, fmt.Errorf("Update too long: %d bytes", totalLength)
}
serializeHeader(buf, uint16(totalLength), UpdateMsg)
buf.Write(convert.Uint16Byte(uint16(withdrawnRoutesLen)))
buf.Write(withdrawBuf.Bytes())
buf.Write(convert.Uint16Byte(uint16(totalPathAttributesLen)))
buf.Write(pathAttributesBuf.Bytes())
buf.Write(nlriBuf.Bytes())
return buf.Bytes(), nil
}
func (b *BGPUpdate) SerializeUpdateAddPath(opt *EncodeOptions) ([]byte, error) {
budget := MaxLen - MinLen
buf := bytes.NewBuffer(nil)
withdrawBuf := bytes.NewBuffer(nil)
for withdraw := b.WithdrawnRoutes; withdraw != nil; withdraw = withdraw.Next {
budget -= int(withdraw.serialize(withdrawBuf, opt.UseAddPath))
if budget < 0 {
return nil, fmt.Errorf("update too long")
}
}
pathAttributesBuf := bytes.NewBuffer(nil)
for pa := b.PathAttributes; pa != nil; pa = pa.Next {
paLen := int(pa.Serialize(pathAttributesBuf, opt))
budget -= paLen
if budget < 0 {
return nil, fmt.Errorf("update too long")
}
}
nlriBuf := bytes.NewBuffer(nil)
for nlri := b.NLRI; nlri != nil; nlri = nlri.Next {
budget -= int(nlri.serialize(nlriBuf, opt.UseAddPath))
if budget < 0 {
return nil, fmt.Errorf("update too long")
}
}
withdrawnRoutesLen := withdrawBuf.Len()
if withdrawnRoutesLen > 65535 {
return nil, fmt.Errorf("Invalid Withdrawn Routes Length: %d", withdrawnRoutesLen)
}
totalPathAttributesLen := pathAttributesBuf.Len()
if totalPathAttributesLen > 65535 {
return nil, fmt.Errorf("Invalid Total Path Attribute Length: %d", totalPathAttributesLen)
}
totalLength := 2 + withdrawnRoutesLen + totalPathAttributesLen + 2 + nlriBuf.Len() + 19
if totalLength > 4096 {
return nil, fmt.Errorf("Update too long: %d bytes", totalLength)
}
serializeHeader(buf, uint16(totalLength), UpdateMsg)
buf.Write(convert.Uint16Byte(uint16(withdrawnRoutesLen)))
buf.Write(withdrawBuf.Bytes())
buf.Write(convert.Uint16Byte(uint16(totalPathAttributesLen)))
buf.Write(pathAttributesBuf.Bytes())
buf.Write(nlriBuf.Bytes())
return buf.Bytes(), nil
}