summaryrefslogtreecommitdiffhomepage
path: root/pkg/packet/bgp/prefix_sid.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/packet/bgp/prefix_sid.go')
-rw-r--r--pkg/packet/bgp/prefix_sid.go303
1 files changed, 303 insertions, 0 deletions
diff --git a/pkg/packet/bgp/prefix_sid.go b/pkg/packet/bgp/prefix_sid.go
new file mode 100644
index 00000000..4ae727f5
--- /dev/null
+++ b/pkg/packet/bgp/prefix_sid.go
@@ -0,0 +1,303 @@
+package bgp
+
+import (
+ "bytes"
+ "encoding/binary"
+ "encoding/json"
+ "fmt"
+)
+
+type PrefixSIDTLVType uint16
+
+type PrefixSIDTLV struct {
+ Type PrefixSIDTLVType
+ Length uint16
+}
+
+type PrefixSIDTLVInterface interface {
+ Len() int
+ DecodeFromBytes([]byte) error
+ Serialize() ([]byte, error)
+ String() string
+ MarshalJSON() ([]byte, error)
+}
+
+type PathAttributePrefixSID struct {
+ PathAttribute
+ TLVs []PrefixSIDTLVInterface
+}
+
+func (s *PrefixSIDTLV) Len() int {
+ return int(s.Length) + tlvHdrLen
+}
+
+func (s *PrefixSIDTLV) Serialize(value []byte) ([]byte, error) {
+ if len(value) != int(s.Length) {
+ return nil, malformedAttrListErr("serialization failed: Prefix SID TLV malformed")
+ }
+
+ buf := make([]byte, tlvHdrLen+len(value))
+ binary.BigEndian.PutUint16(buf[:2], uint16(s.Type))
+ binary.BigEndian.PutUint16(buf[2:4], uint16(s.Length))
+ copy(buf[4:], value)
+
+ return buf, nil
+}
+
+func (s *PrefixSIDTLV) DecodeFromBytes(data []byte) ([]byte, error) {
+ if len(data) < tlvHdrLen {
+ return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
+ }
+ // l.Type = PrefixSIDTLVType(binary.BigEndian.Uint16(data[:2]))
+ // l.Length = binary.BigEndian.Uint16(data[2:4])
+
+ // if len(data) < l.Len() {
+ // return nil, malformedAttrListErr("decoding failed: Prefix SID TLV malformed")
+ // }
+
+ return data[tlvHdrLen:s.Len()], nil
+}
+
+//type LsAttributePrefix struct {
+// IGPFlags *LsIGPFlags `json:"igp_flags,omitempty"`
+// Opaque *[]byte `json:"opaque,omitempty"`
+//
+// SrPrefixSID *uint32 `json:"sr_prefix_sid,omitempty"`
+//}
+
+type PrefixSIDAttribute struct {
+ // Node LsAttributeNode `json:"node"`
+ // Link LsAttributeLink `json:"link"`
+ // Prefix LsAttributePrefix `json:"prefix"`
+}
+
+func (p *PathAttributePrefixSID) Extract() *PrefixSIDAttribute {
+ s := &PrefixSIDAttribute{}
+
+ // for _, tlv := range p.TLVs {
+ // switch v := tlv.(type) {
+ // case *LsTLVNodeFlagBits:
+ // l.Node.Flags = v.Extract()
+
+ // case *LsTLVOpaqueNodeAttr:
+ // l.Node.Opaque = &v.Attr
+
+ // case *LsTLVNodeName:
+ // l.Node.Name = &v.Name
+
+ // case *LsTLVIsisArea:
+ // l.Node.IsisArea = &v.Area
+
+ // case *LsTLVLocalIPv4RouterID:
+ // l.Node.LocalRouterID = &v.IP
+ // l.Link.LocalRouterID = &v.IP
+
+ // case *LsTLVLocalIPv6RouterID:
+ // l.Node.LocalRouterIDv6 = &v.IP
+ // l.Link.LocalRouterIDv6 = &v.IP
+
+ // case *LsTLVSrCapabilities:
+ // l.Node.SrCapabilties = v.Extract()
+
+ // case *LsTLVSrAlgorithm:
+ // l.Node.SrAlgorithms = &v.Algorithm
+
+ // case *LsTLVSrLocalBlock:
+ // l.Node.SrLocalBlock = v.Extract()
+
+ // case *LsTLVRemoteIPv4RouterID:
+ // l.Link.RemoteRouterID = &v.IP
+
+ // case *LsTLVRemoteIPv6RouterID:
+ // l.Link.RemoteRouterIDv6 = &v.IP
+
+ // case *LsTLVAdminGroup:
+ // l.Link.AdminGroup = &v.AdminGroup
+
+ // case *LsTLVMaxLinkBw:
+ // l.Link.Bandwidth = &v.Bandwidth
+
+ // case *LsTLVMaxReservableLinkBw:
+ // l.Link.ReservableBandwidth = &v.Bandwidth
+
+ // case *LsTLVUnreservedBw:
+ // l.Link.UnreservedBandwidth = &v.Bandwidth
+
+ // case *LsTLVSrlg:
+ // l.Link.Srlgs = &v.Srlgs
+
+ // case *LsTLVTEDefaultMetric:
+ // l.Link.DefaultTEMetric = &v.Metric
+
+ // case *LsTLVIGPMetric:
+ // l.Link.IGPMetric = &v.Metric
+
+ // case *LsTLVOpaqueLinkAttr:
+ // l.Link.Opaque = &v.Attr
+
+ // case *LsTLVLinkName:
+ // l.Link.Name = &v.Name
+
+ // case *LsTLVAdjacencySID:
+ // l.Link.SrAdjacencySID = &v.SID
+
+ // case *LsTLVIGPFlags:
+ // l.Prefix.IGPFlags = v.Extract()
+
+ // case *LsTLVOpaquePrefixAttr:
+ // l.Prefix.Opaque = &v.Attr
+
+ // case *LsTLVPrefixSID:
+ // l.Prefix.SrPrefixSID = &v.SID
+ // }
+ // }
+
+ return s
+}
+
+func (p *PathAttributePrefixSID) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
+ tlvs, err := p.PathAttribute.DecodeFromBytes(data)
+ if err != nil {
+ return err
+ }
+
+ for len(tlvs) >= tlvHdrLen {
+ t := &PrefixSIDTLV{}
+ _, err := t.DecodeFromBytes(tlvs)
+ if err != nil {
+ return err
+ }
+
+ var tlv PrefixSIDTLVInterface
+ // switch t.Type {
+ // // Node NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.1)
+ // case LS_TLV_NODE_FLAG_BITS:
+ // tlv = &LsTLVNodeFlagBits{}
+
+ // case LS_TLV_OPAQUE_NODE_ATTR:
+ // tlv = &LsTLVOpaqueNodeAttr{}
+
+ // case LS_TLV_NODE_NAME:
+ // tlv = &LsTLVNodeName{}
+
+ // case LS_TLV_ISIS_AREA:
+ // tlv = &LsTLVIsisArea{}
+
+ // // Used by Link NLRI as well.
+ // case LS_TLV_IPV4_LOCAL_ROUTER_ID:
+ // tlv = &LsTLVLocalIPv4RouterID{}
+
+ // // Used by Link NLRI as well.
+ // case LS_TLV_IPV6_LOCAL_ROUTER_ID:
+ // tlv = &LsTLVLocalIPv6RouterID{}
+
+ // // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Node NLRI
+ // case LS_TLV_SR_CAPABILITIES:
+ // tlv = &LsTLVSrCapabilities{}
+
+ // case LS_TLV_SR_ALGORITHM:
+ // tlv = &LsTLVSrAlgorithm{}
+
+ // case LS_TLV_SR_LOCAL_BLOCK:
+ // tlv = &LsTLVSrLocalBlock{}
+
+ // // Link NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.2)
+ // case LS_TLV_IPV4_REMOTE_ROUTER_ID:
+ // tlv = &LsTLVRemoteIPv4RouterID{}
+
+ // case LS_TLV_IPV6_REMOTE_ROUTER_ID:
+ // tlv = &LsTLVRemoteIPv6RouterID{}
+
+ // case LS_TLV_ADMIN_GROUP:
+ // tlv = &LsTLVAdminGroup{}
+
+ // case LS_TLV_MAX_LINK_BANDWIDTH:
+ // tlv = &LsTLVMaxLinkBw{}
+
+ // case LS_TLV_MAX_RESERVABLE_BANDWIDTH:
+ // tlv = &LsTLVMaxReservableLinkBw{}
+
+ // case LS_TLV_UNRESERVED_BANDWIDTH:
+ // tlv = &LsTLVUnreservedBw{}
+
+ // case LS_TLV_SRLG:
+ // tlv = &LsTLVSrlg{}
+
+ // case LS_TLV_TE_DEFAULT_METRIC:
+ // tlv = &LsTLVTEDefaultMetric{}
+
+ // case LS_TLV_IGP_METRIC:
+ // tlv = &LsTLVIGPMetric{}
+
+ // case LS_TLV_OPAQUE_LINK_ATTR:
+ // tlv = &LsTLVOpaqueLinkAttr{}
+
+ // case LS_TLV_LINK_NAME:
+ // tlv = &LsTLVLinkName{}
+
+ // // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Link NLRI
+ // case LS_TLV_ADJACENCY_SID:
+ // tlv = &LsTLVAdjacencySID{}
+
+ // // Prefix NLRI-related TLVs (https://tools.ietf.org/html/rfc7752#section-3.3.3)
+ // case LS_TLV_IGP_FLAGS:
+ // tlv = &LsTLVIGPFlags{}
+
+ // case LS_TLV_OPAQUE_PREFIX_ATTR:
+ // tlv = &LsTLVOpaquePrefixAttr{}
+
+ // // SR-related TLVs (draft-ietf-idr-bgp-ls-segment-routing-ext-08) for Prefix NLRI
+ // case LS_TLV_PREFIX_SID:
+ // tlv = &LsTLVPrefixSID{}
+
+ // default:
+ // tlvs = tlvs[t.Len():]
+ // continue
+ // }
+
+ if err := tlv.DecodeFromBytes(tlvs); err != nil {
+ return err
+ }
+ tlvs = tlvs[t.Len():]
+
+ p.TLVs = append(p.TLVs, tlv)
+ }
+
+ return nil
+}
+
+func (p *PathAttributePrefixSID) Serialize(options ...*MarshallingOption) ([]byte, error) {
+ buf := []byte{}
+
+ for _, tlv := range p.TLVs {
+ s, err := tlv.Serialize()
+ if err != nil {
+ return nil, err
+ }
+ buf = append(buf, s...)
+ }
+
+ return p.PathAttribute.Serialize(buf, options...)
+}
+
+func (p *PathAttributePrefixSID) String() string {
+ var buf bytes.Buffer
+
+ for _, tlv := range p.TLVs {
+ buf.WriteString(fmt.Sprintf("%s ", tlv.String()))
+ }
+
+ return fmt.Sprintf("{LsAttributes: %s}", buf.String())
+}
+
+func (p *PathAttributePrefixSID) MarshalJSON() ([]byte, error) {
+ return json.Marshal(struct {
+ Type BGPAttrType `json:"type"`
+ Flags BGPAttrFlag `json:"flags"`
+ PrefixSIDAttribute
+ }{
+ p.GetType(),
+ p.GetFlags(),
+ *p.Extract(),
+ })
+}