diff options
Diffstat (limited to 'internal/pkg/apiutil/attribute.go')
-rw-r--r-- | internal/pkg/apiutil/attribute.go | 128 |
1 files changed, 124 insertions, 4 deletions
diff --git a/internal/pkg/apiutil/attribute.go b/internal/pkg/apiutil/attribute.go index 112df6ff..a85ec06b 100644 --- a/internal/pkg/apiutil/attribute.go +++ b/internal/pkg/apiutil/attribute.go @@ -1167,6 +1167,9 @@ func NewTunnelEncapAttributeFromNative(a *bgp.PathAttributeTunnelEncap) *api.Tun Type: uint32(sv.Type), Value: sv.Value, } + + // TODO (sbezverk) Add processing new tunneling sub tlvs + } an, _ := ptypes.MarshalAny(subTlv) subTlvs = append(subTlvs, an) @@ -1611,15 +1614,58 @@ func unmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) { subTlv = bgp.NewTunnelEncapSubTLVProtocol(uint16(sv.Protocol)) case *api.TunnelEncapSubTLVColor: subTlv = bgp.NewTunnelEncapSubTLVColor(sv.Color) - - // TODO (sbezverk) Add processing SR Policy Tunnel sub tlv case *api.TunnelEncapSubTLVSRPreference: subTlv = bgp.NewTunnelEncapSubTLVSRPreference(sv.Flags, sv.Preference) - + case *api.TunnelEncapSubTLVSRPriority: + subTlv = bgp.NewTunnelEncapSubTLVSRPriority(uint8(sv.Priority)) + case *api.TunnelEncapSubTLVSRCandidatePathName: + subTlv = bgp.NewTunnelEncapSubTLVSRCandidatePathName(sv.CandidatePathName) + case *api.TunnelEncapSubTLVSRENLP: + subTlv = bgp.NewTunnelEncapSubTLVSRENLP(sv.Flags, bgp.SRENLPValue(sv.Enlp)) + case *api.TunnelEncapSubTLVSRBindingSID: + var err error + subTlv, err = UnmarshalSRBSID(sv.Bsid) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal tunnel encapsulation attribute sub tlv: %s", err) + } + case *api.TunnelEncapSubTLVSRSegmentList: + var err error + weight := uint32(0) + flags := uint8(0) + if sv.Weight != nil { + weight = sv.Weight.Weight + flags = uint8(sv.Weight.Flags) + } + s := &bgp.TunnelEncapSubTLVSRSegmentList{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST, + Length: uint16(6), // Weight (6 bytes) + length of segment (added later, after all segments are discovered) + }, + Weight: &bgp.SegmentListWeight{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.SegmentListSubTLVWeight, + Length: uint16(6), + }, + Flags: flags, + Weight: weight, + }, + Segments: make([]bgp.TunnelEncapSubTLVInterface, 0), + } + if len(sv.Segments) != 0 { + s.Segments, err = UnmarshalSRSegments(sv.Segments) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal tunnel encapsulation attribute sub tlv: %s", err) + } + } + // Get total length of Segment List Sub TLV + for _, seg := range s.Segments { + s.TunnelEncapSubTLV.Length += uint16(seg.Len() + 2) // Adding 1 byte of type and 1 byte of length for each Segment object + } + subTlv = s case *api.TunnelEncapSubTLVUnknown: subTlv = bgp.NewTunnelEncapSubTLVUnknown(bgp.EncapSubTLVType(sv.Type), sv.Value) default: - return nil, fmt.Errorf("invalid tunnel encapsulation attribute sub tlv: %v", subValue.Message) + return nil, fmt.Errorf("invalid tunnel encapsulation attribute sub tlv: %v type: %T", subValue.Message, sv) } subTlvs = append(subTlvs, subTlv) } @@ -1681,3 +1727,77 @@ func unmarshalAttribute(an *any.Any) (bgp.PathAttributeInterface, error) { } return nil, errors.New("unknown path attribute") } + +// UnmarshalSRBSID unmarshals SR Policy Binding SID Sub TLV and returns native TunnelEncapSubTLVInterface interface +func UnmarshalSRBSID(bsid *any.Any) (bgp.TunnelEncapSubTLVInterface, error) { + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(bsid, &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal tunnel encap sub tlv: %s", err) + } + switch v := value.Message.(type) { + case *api.SRBindingSID: + b, err := bgp.NewBSID(v.Sid) + if err != nil { + return nil, err + } + flags := uint8(0x0) + if v.SFlag { + flags += 0x80 + } + if v.IFlag { + flags += 0x40 + } + return &bgp.TunnelEncapSubTLVSRBSID{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.ENCAP_SUBTLV_TYPE_SRBINDING_SID, + Length: uint16(2 + b.Len()), + }, + BSID: b, + Flags: flags, + }, nil + case *api.SRv6BindingSID: + return nil, fmt.Errorf("srv6 binding sid is not yet supported") + default: + return nil, fmt.Errorf("unknown binding sid type %+v", v) + } +} + +// UnmarshalSRSegments unmarshals SR Policy Segments slice of structs +func UnmarshalSRSegments(s []*any.Any) ([]bgp.TunnelEncapSubTLVInterface, error) { + if len(s) == 0 { + return nil, nil + } + segments := make([]bgp.TunnelEncapSubTLVInterface, len(s)) + for i := 0; i < len(s); i++ { + var value ptypes.DynamicAny + if err := ptypes.UnmarshalAny(s[i], &value); err != nil { + return nil, fmt.Errorf("failed to unmarshal SR Policy Segment: %s", err) + } + switch v := value.Message.(type) { + case *api.SegmentTypeA: + seg := &bgp.SegmentTypeA{ + TunnelEncapSubTLV: bgp.TunnelEncapSubTLV{ + Type: bgp.EncapSubTLVType(bgp.TypeA), + Length: 6, + }, + Label: v.Label << 12, + } + if v.Flags.VFlag { + seg.Flags += 0x80 + } + if v.Flags.AFlag { + seg.Flags += 0x40 + } + if v.Flags.SFlag { + seg.Flags += 0x20 + } + if v.Flags.BFlag { + seg.Flags += 0x10 + } + segments[i] = seg + case *api.SegmentTypeB: + return nil, fmt.Errorf("segment of type B is not yet supported") + } + } + return segments, nil +} |