summaryrefslogtreecommitdiffhomepage
path: root/pkg/packet/bgp/prefix_sid.go
diff options
context:
space:
mode:
authorSerguei Bezverkhi <sbezverk@cisco.com>2020-05-12 22:05:44 -0400
committerFUJITA Tomonori <fujita.tomonori@gmail.com>2020-05-13 12:58:51 +0900
commit833188f52610dcf47c57250788b36625b10a8925 (patch)
tree2c4f80208c1d40bc0e52a2f379421039fe577f56 /pkg/packet/bgp/prefix_sid.go
parent95745b6cf9a5ed229c5494bb0b531215dec38dbe (diff)
extend attributes proto for Prefix SID support
Signed-off-by: Serguei Bezverkhi <sbezverk@cisco.com>
Diffstat (limited to 'pkg/packet/bgp/prefix_sid.go')
-rw-r--r--pkg/packet/bgp/prefix_sid.go143
1 files changed, 139 insertions, 4 deletions
diff --git a/pkg/packet/bgp/prefix_sid.go b/pkg/packet/bgp/prefix_sid.go
index 7dd90082..a7983bcd 100644
--- a/pkg/packet/bgp/prefix_sid.go
+++ b/pkg/packet/bgp/prefix_sid.go
@@ -5,6 +5,10 @@ import (
"encoding/binary"
"encoding/json"
"fmt"
+ "net"
+
+ "github.com/golang/protobuf/ptypes"
+ api "github.com/osrg/gobgp/api"
)
const (
@@ -14,9 +18,8 @@ const (
type TLVType uint8
type TLV struct {
- Type TLVType
- Length uint16
- Reserved uint8
+ Type TLVType
+ Length uint16
}
func (s *TLV) Len() int {
@@ -391,7 +394,7 @@ func (s *SRv6InformationSubTLV) MarshalJSON() ([]byte, error) {
func (s *SRv6InformationSubTLV) String() string {
var buf bytes.Buffer
- buf.WriteString(fmt.Sprintf("SID: %s ", string(s.SID)))
+ buf.WriteString(fmt.Sprintf("SID: %s ", net.IP(s.SID).To16().String()))
buf.WriteString(fmt.Sprintf("Flag: %d ", s.Flags))
buf.WriteString(fmt.Sprintf("Endpoint Behavior: %d ", s.EndpointBehavior))
for _, tlv := range s.SubSubTLVs {
@@ -540,3 +543,135 @@ func (s *SRv6SIDStructureSubSubTLV) String() string {
s.TranspositionOffset,
)
}
+
+func NewPathAttributePrefixSID(psid *api.PrefixSID) (*PathAttributePrefixSID, error) {
+ t := BGP_ATTR_TYPE_PREFIX_SID
+ s := &PathAttributePrefixSID{
+ PathAttribute: PathAttribute{
+ Flags: PathAttrFlags[t],
+ Type: t,
+ },
+ TLVs: make([]PrefixSIDTLVInterface, 0),
+ }
+ for _, raw := range psid.Tlvs {
+ var tlv ptypes.DynamicAny
+ if err := ptypes.UnmarshalAny(raw, &tlv); err != nil {
+ return nil, err
+ }
+ switch v := tlv.Message.(type) {
+ case *api.SRv6L3ServiceTLV:
+ tlvLength, tlvs, err := UnmarshalSubTLVs(v.SubTlvs)
+ if err != nil {
+ return nil, err
+ }
+ o := &SRv6L3ServiceAttribute{
+ TLV: TLV{
+ Type: TLVType(5),
+ Length: tlvLength,
+ },
+ }
+ s.PathAttribute.Length += tlvLength
+ // Storing Sub TLVs in a Service TLV
+ o.SubTLVs = append(o.SubTLVs, tlvs...)
+ // Adding Service TLV to Path Attribute TLV slice.
+ s.TLVs = append(s.TLVs, o)
+ default:
+ return nil, fmt.Errorf("unknown or not implemented Prefix SID type: %+v", v)
+ }
+ }
+ // Final Path Attribute Length is 3 bytes of the header and 1 byte Reserved1
+ s.PathAttribute.Length += (3 + 1)
+ return s, nil
+}
+
+func UnmarshalSubTLVs(stlvs map[uint32]*api.SRv6TLV) (uint16, []PrefixSIDTLVInterface, error) {
+ p := make([]PrefixSIDTLVInterface, 0, len(stlvs))
+ l := uint16(0)
+ // v.SubTlvs is a map by sub tlv type and the value is a slice of sub tlvs of the specific type
+ for t, tlv := range stlvs {
+ switch t {
+ case 1:
+ // Sub TLV Type 1 is SRv6 Informational Sub TLV
+ for _, stlvRaw := range tlv.Tlv {
+ // Instantiating Information Sub TLV
+ info := &SRv6InformationSubTLV{
+ SubTLV: SubTLV{
+ Type: SubTLVType(1),
+ },
+ SubSubTLVs: make([]PrefixSIDTLVInterface, 0),
+ }
+ var raw ptypes.DynamicAny
+ if err := ptypes.UnmarshalAny(stlvRaw, &raw); err != nil {
+ return 0, nil, err
+ }
+ infoProto := raw.Message.(*api.SRv6InformationSubTLV)
+ info.SID = make([]byte, len(infoProto.Sid))
+ copy(info.SID, infoProto.Sid)
+ // TODO Once RFC is published add processing of flags
+ info.Flags = 0
+ info.EndpointBehavior = uint16(infoProto.EndpointBehavior)
+ var sstlvslength uint16
+ var sstlvs []PrefixSIDTLVInterface
+ if len(infoProto.SubSubTlvs) != 0 {
+ // Processing Sub Sub TLVs
+ var err error
+ sstlvslength, sstlvs, err = UnmarshalSubSubTLVs(infoProto.SubSubTlvs)
+ if err != nil {
+ return 0, nil, err
+ }
+ info.SubSubTLVs = append(info.SubSubTLVs, sstlvs...)
+ }
+ // SRv6 Information Sub TLV length consists 1 byte Resrved2, 16 bytes SID, 1 byte flags, 2 bytes Endpoint Behavior
+ // 1 byte Reserved3 and length of Sub Sub TLVs
+ info.SubTLV.Length = 1 + 16 + 1 + 2 + 1 + sstlvslength
+ // For total Srv6 Information Sub TLV length, adding 3 bytes of the Sub TLV header
+ l += info.SubTLV.Length + 4
+ p = append(p, info)
+ }
+ default:
+ return 0, nil, fmt.Errorf("unknown or not implemented Prefix SID Sub TLV type: %d", t)
+ }
+ }
+
+ return l, p, nil
+}
+
+func UnmarshalSubSubTLVs(stlvs map[uint32]*api.SRv6TLV) (uint16, []PrefixSIDTLVInterface, error) {
+ p := make([]PrefixSIDTLVInterface, 0)
+ l := uint16(0)
+ // v.SubTlvs is a map by sub tlv type and the value is a slice of sub tlvs of the specific type
+ for t, tlv := range stlvs {
+ switch t {
+ case 1:
+ // Sub Sub TLV Type 1 is SRv6 Structure Sub Sub TLV
+ for _, stlvRaw := range tlv.Tlv {
+ // Instantiating Information Sub TLV
+ structure := &SRv6SIDStructureSubSubTLV{
+ SubSubTLV: SubSubTLV{
+ Type: SubSubTLVType(1),
+ Length: 6,
+ },
+ }
+ var raw ptypes.DynamicAny
+ if err := ptypes.UnmarshalAny(stlvRaw, &raw); err != nil {
+ return 0, nil, err
+ }
+ structureProto := raw.Message.(*api.SRv6StructureSubSubTLV)
+ structure.LocalBlockLength = uint8(structureProto.LocalBlockLength)
+ structure.LocatorNodeLength = uint8(structureProto.LocalNodeLength)
+ structure.FunctionLength = uint8(structureProto.FunctionLength)
+ structure.ArgumentLength = uint8(structureProto.ArgumentLength)
+ structure.TranspositionLength = uint8(structureProto.TranspositionLength)
+ structure.TranspositionOffset = uint8(structureProto.TranspositionOffset)
+
+ // SRv6 Structure Sub Sub TLV length consists of header 3 bytes, 6 bytes of value
+ l += (3 + 6)
+ p = append(p, structure)
+ }
+ default:
+ return 0, nil, fmt.Errorf("unknown or not implemented Prefix SID Sub TLV type: %d", t)
+ }
+ }
+
+ return l, p, nil
+}