diff options
author | Serguei Bezverkhi <sbezverk@cisco.com> | 2020-11-25 17:29:13 -0500 |
---|---|---|
committer | Serguei Bezverkhi <sbezverk@cisco.com> | 2020-11-25 17:29:13 -0500 |
commit | 48e55b7c388dd6912f4c7f39998723b4ab6159e3 (patch) | |
tree | 242bfba54e72ca8bc8cfbe0a77200b5b79e8c58e | |
parent | 66413b5335790dc9110b80c8cffe31b3259df9d2 (diff) |
code changes
Signed-off-by: Serguei Bezverkhi <sbezverk@cisco.com>
-rw-r--r-- | internal/pkg/apiutil/attribute.go | 12 | ||||
-rw-r--r-- | internal/pkg/config/bgp_configs.go | 18 | ||||
-rw-r--r-- | pkg/packet/bgp/bgp.go | 183 | ||||
-rw-r--r-- | pkg/packet/bgp/sr_policy.go | 721 | ||||
-rw-r--r-- | tools/pyang_plugins/gobgp.yang | 14 |
5 files changed, 873 insertions, 75 deletions
diff --git a/internal/pkg/apiutil/attribute.go b/internal/pkg/apiutil/attribute.go index 9d70802b..112df6ff 100644 --- a/internal/pkg/apiutil/attribute.go +++ b/internal/pkg/apiutil/attribute.go @@ -768,6 +768,13 @@ func UnmarshalNLRI(rf bgp.RouteFamily, an *any.Any) (bgp.AddrPrefixInterface, er } nlri = bgp.NewEVPNIPPrefixRoute(rd, *esi, v.EthernetTag, uint8(v.IpPrefixLen), v.IpPrefix, v.GwAddress, v.Label) } + case *api.SRPolicyNLRI: + switch rf { + case bgp.RF_SR_POLICY_IPv4: + nlri = bgp.NewSRPolicyIPv4(v.Length, v.Distinguisher, v.Color, v.Endpoint) + case bgp.RF_SR_POLICY_IPv6: + nlri = bgp.NewSRPolicyIPv6(v.Length, v.Distinguisher, v.Color, v.Endpoint) + } case *api.LabeledVPNIPAddressPrefix: rd, err := UnmarshalRD(v.Rd) if err != nil { @@ -1604,6 +1611,11 @@ 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.TunnelEncapSubTLVUnknown: subTlv = bgp.NewTunnelEncapSubTLVUnknown(bgp.EncapSubTLVType(sv.Type), sv.Value) default: diff --git a/internal/pkg/config/bgp_configs.go b/internal/pkg/config/bgp_configs.go index b421a440..6d8fd26c 100644 --- a/internal/pkg/config/bgp_configs.go +++ b/internal/pkg/config/bgp_configs.go @@ -260,6 +260,8 @@ const ( AFI_SAFI_TYPE_IPV6_FLOWSPEC AfiSafiType = "ipv6-flowspec" AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC AfiSafiType = "l3vpn-ipv6-flowspec" AFI_SAFI_TYPE_L2VPN_FLOWSPEC AfiSafiType = "l2vpn-flowspec" + AFI_SAFI_TYPE_IPV4_SRPOLICY AfiSafiType = "ipv4-srpolicy" + AFI_SAFI_TYPE_IPV6_SRPOLICY AfiSafiType = "ipv6-srpolicy" AFI_SAFI_TYPE_OPAQUE AfiSafiType = "opaque" AFI_SAFI_TYPE_LS AfiSafiType = "ls" ) @@ -285,8 +287,10 @@ var AfiSafiTypeToIntMap = map[AfiSafiType]int{ AFI_SAFI_TYPE_IPV6_FLOWSPEC: 17, AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC: 18, AFI_SAFI_TYPE_L2VPN_FLOWSPEC: 19, - AFI_SAFI_TYPE_OPAQUE: 20, - AFI_SAFI_TYPE_LS: 21, + AFI_SAFI_TYPE_IPV4_SRPOLICY: 20, + AFI_SAFI_TYPE_IPV6_SRPOLICY: 21, + AFI_SAFI_TYPE_OPAQUE: 22, + AFI_SAFI_TYPE_LS: 23, } var IntToAfiSafiTypeMap = map[int]AfiSafiType{ @@ -310,8 +314,10 @@ var IntToAfiSafiTypeMap = map[int]AfiSafiType{ 17: AFI_SAFI_TYPE_IPV6_FLOWSPEC, 18: AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC, 19: AFI_SAFI_TYPE_L2VPN_FLOWSPEC, - 20: AFI_SAFI_TYPE_OPAQUE, - 21: AFI_SAFI_TYPE_LS, + 20: AFI_SAFI_TYPE_IPV4_SRPOLICY, + 21: AFI_SAFI_TYPE_IPV6_SRPOLICY, + 22: AFI_SAFI_TYPE_OPAQUE, + 23: AFI_SAFI_TYPE_LS, } func (v AfiSafiType) Validate() error { @@ -1135,7 +1141,7 @@ type ZebraState struct { MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"` // original -> gobgp:software-name // Configure zebra software name. - // quagga, frr3, frr4, frr5, frr6, frr7 can be used. + // frr4, cumulus, frr6, frr7, and frr7.2 can be used. SoftwareName string `mapstructure:"software-name" json:"software-name,omitempty"` } @@ -1165,7 +1171,7 @@ type ZebraConfig struct { MplsLabelRangeSize uint32 `mapstructure:"mpls-label-range-size" json:"mpls-label-range-size,omitempty"` // original -> gobgp:software-name // Configure zebra software name. - // quagga, frr3, frr4, frr5, frr6, frr7 can be used. + // frr4, cumulus, frr6, frr7, and frr7.2 can be used. SoftwareName string `mapstructure:"software-name" json:"software-name,omitempty"` } diff --git a/pkg/packet/bgp/bgp.go b/pkg/packet/bgp/bgp.go index ee4feb09..0976935e 100644 --- a/pkg/packet/bgp/bgp.go +++ b/pkg/packet/bgp/bgp.go @@ -79,6 +79,7 @@ const ( SAFI_VPLS = 65 SAFI_EVPN = 70 SAFI_LS = 71 + SAFI_SRPOLICY = 73 SAFI_MPLS_VPN = 128 SAFI_MPLS_VPN_MULTICAST = 129 SAFI_ROUTE_TARGET_CONSTRAINTS = 132 @@ -184,6 +185,7 @@ const ( TUNNEL_TYPE_MPLS_IN_GRE TunnelType = 11 TUNNEL_TYPE_VXLAN_GRE TunnelType = 12 TUNNEL_TYPE_MPLS_IN_UDP TunnelType = 13 + TUNNEL_TYPE_SR_POLICY TunnelType = 15 ) func (p TunnelType) String() string { @@ -206,6 +208,8 @@ func (p TunnelType) String() string { return "vxlan-gre" case TUNNEL_TYPE_MPLS_IN_UDP: return "mpls-in-udp" + case TUNNEL_TYPE_SR_POLICY: + return "sr-policy" default: return fmt.Sprintf("TunnelType(%d)", uint8(p)) } @@ -250,9 +254,16 @@ func (p PmsiTunnelType) String() string { type EncapSubTLVType uint8 const ( - ENCAP_SUBTLV_TYPE_ENCAPSULATION EncapSubTLVType = 1 - ENCAP_SUBTLV_TYPE_PROTOCOL EncapSubTLVType = 2 - ENCAP_SUBTLV_TYPE_COLOR EncapSubTLVType = 4 + ENCAP_SUBTLV_TYPE_ENCAPSULATION EncapSubTLVType = 1 + ENCAP_SUBTLV_TYPE_PROTOCOL EncapSubTLVType = 2 + ENCAP_SUBTLV_TYPE_COLOR EncapSubTLVType = 4 + ENCAP_SUBTLV_TYPE_SRPREFIX_SID EncapSubTLVType = 11 + ENCAP_SUBTLV_TYPE_SRPREFERENCE EncapSubTLVType = 12 + ENCAP_SUBTLV_TYPE_SRBINDING_SID EncapSubTLVType = 13 + ENCAP_SUBTLV_TYPE_SRENLP EncapSubTLVType = 14 + ENCAP_SUBTLV_TYPE_SRPRIORITY EncapSubTLVType = 15 + ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST EncapSubTLVType = 128 + ENCAP_SUBTLV_TYPE_SRPOLICY_NAME EncapSubTLVType = 129 ) const ( @@ -8129,78 +8140,84 @@ func (f RouteFamily) String() string { } const ( - RF_IPv4_UC RouteFamily = AFI_IP<<16 | SAFI_UNICAST - RF_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_UNICAST - RF_IPv4_MC RouteFamily = AFI_IP<<16 | SAFI_MULTICAST - RF_IPv6_MC RouteFamily = AFI_IP6<<16 | SAFI_MULTICAST - RF_IPv4_VPN RouteFamily = AFI_IP<<16 | SAFI_MPLS_VPN - RF_IPv6_VPN RouteFamily = AFI_IP6<<16 | SAFI_MPLS_VPN - RF_IPv4_VPN_MC RouteFamily = AFI_IP<<16 | SAFI_MPLS_VPN_MULTICAST - RF_IPv6_VPN_MC RouteFamily = AFI_IP6<<16 | SAFI_MPLS_VPN_MULTICAST - RF_IPv4_MPLS RouteFamily = AFI_IP<<16 | SAFI_MPLS_LABEL - RF_IPv6_MPLS RouteFamily = AFI_IP6<<16 | SAFI_MPLS_LABEL - RF_VPLS RouteFamily = AFI_L2VPN<<16 | SAFI_VPLS - RF_EVPN RouteFamily = AFI_L2VPN<<16 | SAFI_EVPN - RF_RTC_UC RouteFamily = AFI_IP<<16 | SAFI_ROUTE_TARGET_CONSTRAINTS - RF_IPv4_ENCAP RouteFamily = AFI_IP<<16 | SAFI_ENCAPSULATION - RF_IPv6_ENCAP RouteFamily = AFI_IP6<<16 | SAFI_ENCAPSULATION - RF_FS_IPv4_UC RouteFamily = AFI_IP<<16 | SAFI_FLOW_SPEC_UNICAST - RF_FS_IPv4_VPN RouteFamily = AFI_IP<<16 | SAFI_FLOW_SPEC_VPN - RF_FS_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_UNICAST - RF_FS_IPv6_VPN RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_VPN - RF_FS_L2_VPN RouteFamily = AFI_L2VPN<<16 | SAFI_FLOW_SPEC_VPN - RF_OPAQUE RouteFamily = AFI_OPAQUE<<16 | SAFI_KEY_VALUE - RF_LS RouteFamily = AFI_LS<<16 | SAFI_LS + RF_IPv4_UC RouteFamily = AFI_IP<<16 | SAFI_UNICAST + RF_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_UNICAST + RF_IPv4_MC RouteFamily = AFI_IP<<16 | SAFI_MULTICAST + RF_IPv6_MC RouteFamily = AFI_IP6<<16 | SAFI_MULTICAST + RF_IPv4_VPN RouteFamily = AFI_IP<<16 | SAFI_MPLS_VPN + RF_IPv6_VPN RouteFamily = AFI_IP6<<16 | SAFI_MPLS_VPN + RF_IPv4_VPN_MC RouteFamily = AFI_IP<<16 | SAFI_MPLS_VPN_MULTICAST + RF_IPv6_VPN_MC RouteFamily = AFI_IP6<<16 | SAFI_MPLS_VPN_MULTICAST + RF_IPv4_MPLS RouteFamily = AFI_IP<<16 | SAFI_MPLS_LABEL + RF_IPv6_MPLS RouteFamily = AFI_IP6<<16 | SAFI_MPLS_LABEL + RF_VPLS RouteFamily = AFI_L2VPN<<16 | SAFI_VPLS + RF_EVPN RouteFamily = AFI_L2VPN<<16 | SAFI_EVPN + RF_RTC_UC RouteFamily = AFI_IP<<16 | SAFI_ROUTE_TARGET_CONSTRAINTS + RF_IPv4_ENCAP RouteFamily = AFI_IP<<16 | SAFI_ENCAPSULATION + RF_IPv6_ENCAP RouteFamily = AFI_IP6<<16 | SAFI_ENCAPSULATION + RF_FS_IPv4_UC RouteFamily = AFI_IP<<16 | SAFI_FLOW_SPEC_UNICAST + RF_FS_IPv4_VPN RouteFamily = AFI_IP<<16 | SAFI_FLOW_SPEC_VPN + RF_FS_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_UNICAST + RF_FS_IPv6_VPN RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_VPN + RF_FS_L2_VPN RouteFamily = AFI_L2VPN<<16 | SAFI_FLOW_SPEC_VPN + RF_OPAQUE RouteFamily = AFI_OPAQUE<<16 | SAFI_KEY_VALUE + RF_LS RouteFamily = AFI_LS<<16 | SAFI_LS + RF_SR_POLICY_IPv4 RouteFamily = AFI_IP<<16 | SAFI_SRPOLICY + RF_SR_POLICY_IPv6 RouteFamily = AFI_IP6<<16 | SAFI_SRPOLICY ) var AddressFamilyNameMap = map[RouteFamily]string{ - RF_IPv4_UC: "ipv4-unicast", - RF_IPv6_UC: "ipv6-unicast", - RF_IPv4_MC: "ipv4-multicast", - RF_IPv6_MC: "ipv6-multicast", - RF_IPv4_MPLS: "ipv4-labelled-unicast", - RF_IPv6_MPLS: "ipv6-labelled-unicast", - RF_IPv4_VPN: "l3vpn-ipv4-unicast", - RF_IPv6_VPN: "l3vpn-ipv6-unicast", - RF_IPv4_VPN_MC: "l3vpn-ipv4-multicast", - RF_IPv6_VPN_MC: "l3vpn-ipv6-multicast", - RF_VPLS: "l2vpn-vpls", - RF_EVPN: "l2vpn-evpn", - RF_RTC_UC: "rtc", - RF_IPv4_ENCAP: "ipv4-encap", - RF_IPv6_ENCAP: "ipv6-encap", - RF_FS_IPv4_UC: "ipv4-flowspec", - RF_FS_IPv4_VPN: "l3vpn-ipv4-flowspec", - RF_FS_IPv6_UC: "ipv6-flowspec", - RF_FS_IPv6_VPN: "l3vpn-ipv6-flowspec", - RF_FS_L2_VPN: "l2vpn-flowspec", - RF_OPAQUE: "opaque", - RF_LS: "ls", + RF_IPv4_UC: "ipv4-unicast", + RF_IPv6_UC: "ipv6-unicast", + RF_IPv4_MC: "ipv4-multicast", + RF_IPv6_MC: "ipv6-multicast", + RF_IPv4_MPLS: "ipv4-labelled-unicast", + RF_IPv6_MPLS: "ipv6-labelled-unicast", + RF_IPv4_VPN: "l3vpn-ipv4-unicast", + RF_IPv6_VPN: "l3vpn-ipv6-unicast", + RF_IPv4_VPN_MC: "l3vpn-ipv4-multicast", + RF_IPv6_VPN_MC: "l3vpn-ipv6-multicast", + RF_VPLS: "l2vpn-vpls", + RF_EVPN: "l2vpn-evpn", + RF_RTC_UC: "rtc", + RF_IPv4_ENCAP: "ipv4-encap", + RF_IPv6_ENCAP: "ipv6-encap", + RF_FS_IPv4_UC: "ipv4-flowspec", + RF_FS_IPv4_VPN: "l3vpn-ipv4-flowspec", + RF_FS_IPv6_UC: "ipv6-flowspec", + RF_FS_IPv6_VPN: "l3vpn-ipv6-flowspec", + RF_FS_L2_VPN: "l2vpn-flowspec", + RF_OPAQUE: "opaque", + RF_LS: "ls", + RF_SR_POLICY_IPv4: "ipv4-srpolicy", + RF_SR_POLICY_IPv6: "ipv6-srpolicy", } var AddressFamilyValueMap = map[string]RouteFamily{ - AddressFamilyNameMap[RF_IPv4_UC]: RF_IPv4_UC, - AddressFamilyNameMap[RF_IPv6_UC]: RF_IPv6_UC, - AddressFamilyNameMap[RF_IPv4_MC]: RF_IPv4_MC, - AddressFamilyNameMap[RF_IPv6_MC]: RF_IPv6_MC, - AddressFamilyNameMap[RF_IPv4_MPLS]: RF_IPv4_MPLS, - AddressFamilyNameMap[RF_IPv6_MPLS]: RF_IPv6_MPLS, - AddressFamilyNameMap[RF_IPv4_VPN]: RF_IPv4_VPN, - AddressFamilyNameMap[RF_IPv6_VPN]: RF_IPv6_VPN, - AddressFamilyNameMap[RF_IPv4_VPN_MC]: RF_IPv4_VPN_MC, - AddressFamilyNameMap[RF_IPv6_VPN_MC]: RF_IPv6_VPN_MC, - AddressFamilyNameMap[RF_VPLS]: RF_VPLS, - AddressFamilyNameMap[RF_EVPN]: RF_EVPN, - AddressFamilyNameMap[RF_RTC_UC]: RF_RTC_UC, - AddressFamilyNameMap[RF_IPv4_ENCAP]: RF_IPv4_ENCAP, - AddressFamilyNameMap[RF_IPv6_ENCAP]: RF_IPv6_ENCAP, - AddressFamilyNameMap[RF_FS_IPv4_UC]: RF_FS_IPv4_UC, - AddressFamilyNameMap[RF_FS_IPv4_VPN]: RF_FS_IPv4_VPN, - AddressFamilyNameMap[RF_FS_IPv6_UC]: RF_FS_IPv6_UC, - AddressFamilyNameMap[RF_FS_IPv6_VPN]: RF_FS_IPv6_VPN, - AddressFamilyNameMap[RF_FS_L2_VPN]: RF_FS_L2_VPN, - AddressFamilyNameMap[RF_OPAQUE]: RF_OPAQUE, - AddressFamilyNameMap[RF_LS]: RF_LS, + AddressFamilyNameMap[RF_IPv4_UC]: RF_IPv4_UC, + AddressFamilyNameMap[RF_IPv6_UC]: RF_IPv6_UC, + AddressFamilyNameMap[RF_IPv4_MC]: RF_IPv4_MC, + AddressFamilyNameMap[RF_IPv6_MC]: RF_IPv6_MC, + AddressFamilyNameMap[RF_IPv4_MPLS]: RF_IPv4_MPLS, + AddressFamilyNameMap[RF_IPv6_MPLS]: RF_IPv6_MPLS, + AddressFamilyNameMap[RF_IPv4_VPN]: RF_IPv4_VPN, + AddressFamilyNameMap[RF_IPv6_VPN]: RF_IPv6_VPN, + AddressFamilyNameMap[RF_IPv4_VPN_MC]: RF_IPv4_VPN_MC, + AddressFamilyNameMap[RF_IPv6_VPN_MC]: RF_IPv6_VPN_MC, + AddressFamilyNameMap[RF_VPLS]: RF_VPLS, + AddressFamilyNameMap[RF_EVPN]: RF_EVPN, + AddressFamilyNameMap[RF_RTC_UC]: RF_RTC_UC, + AddressFamilyNameMap[RF_IPv4_ENCAP]: RF_IPv4_ENCAP, + AddressFamilyNameMap[RF_IPv6_ENCAP]: RF_IPv6_ENCAP, + AddressFamilyNameMap[RF_FS_IPv4_UC]: RF_FS_IPv4_UC, + AddressFamilyNameMap[RF_FS_IPv4_VPN]: RF_FS_IPv4_VPN, + AddressFamilyNameMap[RF_FS_IPv6_UC]: RF_FS_IPv6_UC, + AddressFamilyNameMap[RF_FS_IPv6_VPN]: RF_FS_IPv6_VPN, + AddressFamilyNameMap[RF_FS_L2_VPN]: RF_FS_L2_VPN, + AddressFamilyNameMap[RF_OPAQUE]: RF_OPAQUE, + AddressFamilyNameMap[RF_LS]: RF_LS, + AddressFamilyNameMap[RF_SR_POLICY_IPv4]: RF_SR_POLICY_IPv4, + AddressFamilyNameMap[RF_SR_POLICY_IPv6]: RF_SR_POLICY_IPv6, } func GetRouteFamily(name string) (RouteFamily, error) { @@ -8246,6 +8263,20 @@ func NewPrefixFromRouteFamily(afi uint16, safi uint8, prefixStr ...string) (pref prefix = NewLabeledIPv6AddrPrefix(0, "", *NewMPLSLabelStack()) case RF_EVPN: prefix = NewEVPNNLRI(0, nil) + + // TODO (sbezverk) Add processing SR Policy NLRI + case RF_SR_POLICY_IPv4: + prefix = &SRPolicyIPv4{ + SRPolicyNLRI: SRPolicyNLRI{ + rf: RF_SR_POLICY_IPv4, + }, + } + case RF_SR_POLICY_IPv6: + prefix = &SRPolicyIPv6{ + SRPolicyNLRI: SRPolicyNLRI{ + rf: RF_SR_POLICY_IPv6, + }, + } case RF_RTC_UC: prefix = &RouteTargetMembershipNLRI{} case RF_IPv4_ENCAP: @@ -10297,6 +10328,8 @@ func (e *EncapExtended) String() string { return "VXLAN GRE" case TUNNEL_TYPE_MPLS_IN_UDP: return "MPLS in UDP" + case TUNNEL_TYPE_SR_POLICY: + return "SR Policy" default: return fmt.Sprintf("tunnel: %d", e.TunnelType) } @@ -11602,6 +11635,18 @@ func (t *TunnelEncapTLV) DecodeFromBytes(data []byte) error { subTlv = &TunnelEncapSubTLVProtocol{} case ENCAP_SUBTLV_TYPE_COLOR: subTlv = &TunnelEncapSubTLVColor{} + case ENCAP_SUBTLV_TYPE_SRPREFERENCE: + subTlv = &TunnelEncapSubTLVSRPreference{} + case ENCAP_SUBTLV_TYPE_SRBINDING_SID: + subTlv = &TunnelEncapSubTLVSRBSID{} + case ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST: + subTlv = &TunnelEncapSubTLVSRSegmentList{} + case ENCAP_SUBTLV_TYPE_SRENLP: + subTlv = &TunnelEncapSubTLVSRENLP{} + case ENCAP_SUBTLV_TYPE_SRPRIORITY: + subTlv = &TunnelEncapSubTLVSRPriority{} + case ENCAP_SUBTLV_TYPE_SRPOLICY_NAME: + subTlv = &TunnelEncapSubTLVSRPolicyName{} default: subTlv = &TunnelEncapSubTLVUnknown{ TunnelEncapSubTLV: TunnelEncapSubTLV{ diff --git a/pkg/packet/bgp/sr_policy.go b/pkg/packet/bgp/sr_policy.go new file mode 100644 index 00000000..007612c4 --- /dev/null +++ b/pkg/packet/bgp/sr_policy.go @@ -0,0 +1,721 @@ +package bgp + +import ( + "encoding/binary" + "encoding/json" + "fmt" + "net" + "strconv" +) + +type SRPolicyNLRI struct { + PrefixDefault + rf RouteFamily + Length uint8 + Distinguisher uint32 + Color uint32 + Endpoint []byte +} + +const ( + // SRPolicyIPv4NLRILen defines IPv4 SR Policy NLRI portion length in bits + SRPolicyIPv4NLRILen = 96 + // SRPolicyIPv6NLRILen defines IPv6 SR Policy NLRI portion length in bits + SRPolicyIPv6NLRILen = 192 +) + +func (s *SRPolicyNLRI) Flat() map[string]string { + return map[string]string{} +} + +func (s *SRPolicyNLRI) decodeFromBytes(rf RouteFamily, data []byte, options ...*MarshallingOption) error { + if IsAddPathEnabled(true, rf, options) { + var err error + data, err = s.decodePathIdentifier(data) + if err != nil { + return err + } + } + switch data[0] { + case SRPolicyIPv4NLRILen: + s.rf = RF_SR_POLICY_IPv4 + case SRPolicyIPv6NLRILen: + s.rf = RF_SR_POLICY_IPv6 + default: + msg := fmt.Sprintf("Invalid length %d for SR Policy NLRI", len(data)) + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg) + } + p := 0 + s.Length = data[p] / 8 + p++ + s.Distinguisher = binary.BigEndian.Uint32(data[p : p+4]) + p += 4 + s.Color = binary.BigEndian.Uint32(data[p : p+4]) + p += 4 + s.Endpoint = data[p:] + + return nil +} + +func (s *SRPolicyNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) { + buf := make([]byte, 1+s.Length) + p := 0 + buf[0] = s.Length + p++ + binary.BigEndian.PutUint32(buf[:4], s.Distinguisher) + p += 4 + binary.BigEndian.PutUint32(buf[:4], s.Color) + p += 4 + copy(buf[p:], s.Endpoint) + if IsAddPathEnabled(false, s.rf, options) { + id, err := s.serializeIdentifier() + if err != nil { + return nil, err + } + return append(id, buf...), nil + } + return buf, nil +} + +func (s *SRPolicyNLRI) AFI() uint16 { + afi, _ := RouteFamilyToAfiSafi(s.rf) + return afi +} + +func (s *SRPolicyNLRI) SAFI() uint8 { + _, safi := RouteFamilyToAfiSafi(s.rf) + return safi +} + +func (s *SRPolicyNLRI) Len(options ...*MarshallingOption) int { + buf, _ := s.Serialize(options...) + return len(buf) +} + +func (s *SRPolicyNLRI) String() string { + afi, _ := RouteFamilyToAfiSafi(s.rf) + var endp string + switch afi { + case AFI_IP: + endp = net.IP(s.Endpoint).To4().String() + case AFI_IP6: + endp = net.IP(s.Endpoint).To16().String() + default: + endp = "[" + string(s.Endpoint) + "]" + } + return fmt.Sprintf("{ Length: %d (bytes), Distinguisher: %d, Color %d, Endpoint: %s }", s.Length, s.Distinguisher, s.Color, endp) +} + +func (s *SRPolicyNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Length uint8 `json:"length"` + Distinguisher uint32 `json:"distinguisher"` + Color uint32 `json:"color"` + Endpoint string `json:"endpoint"` + }{ + Length: s.Length, + Distinguisher: s.Distinguisher, + Color: s.Color, + Endpoint: string(s.Endpoint), + }) +} + +type SRPolicyIPv4 struct { + SRPolicyNLRI +} + +func (s *SRPolicyIPv4) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + return s.decodeFromBytes(s.rf, data) +} + +func NewSRPolicyIPv4(l uint32, d uint32, c uint32, ep []byte) *SRPolicyIPv4 { + fmt.Printf("><SB> NewSRPolicyIPv4: length: %d distinguisher: %d color: %d endpoint: %+v\n", l, d, c, ep) + return &SRPolicyIPv4{ + SRPolicyNLRI: SRPolicyNLRI{ + rf: RF_SR_POLICY_IPv4, + Length: uint8(l), + Distinguisher: d, + Color: c, + Endpoint: ep, + }, + } +} + +type SRPolicyIPv6 struct { + SRPolicyNLRI +} + +func (s *SRPolicyIPv6) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { + return s.decodeFromBytes(s.rf, data) +} + +func NewSRPolicyIPv6(l uint32, d uint32, c uint32, ep []byte) *SRPolicyIPv6 { + fmt.Printf("><SB> NewSRPolicyIPv6: length: %d distinguisher: %d color: %d endpoint: %+v\n", l, d, c, ep) + return &SRPolicyIPv6{ + SRPolicyNLRI: SRPolicyNLRI{ + rf: RF_SR_POLICY_IPv6, + Length: uint8(l), + Distinguisher: d, + Color: c, + Endpoint: ep, + }, + } +} + +type TunnelEncapSubTLVSRPreference struct { + TunnelEncapSubTLV + Flags uint8 + Preference uint32 +} + +func (t *TunnelEncapSubTLVSRPreference) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + // Second byte carries the length of SR Preference SubTLV + if t.Length != 6 { + msg := fmt.Sprintf("Invalid TunnelEncapSubTLVSRPreference length: %d", t.Length) + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg) + } + t.Flags = value[0] + t.Preference = binary.BigEndian.Uint32(value[2:6]) + return nil +} + +func (t *TunnelEncapSubTLVSRPreference) Serialize() ([]byte, error) { + buf := make([]byte, t.Length) + buf[0] = t.Flags + binary.BigEndian.PutUint32(buf[2:6], t.Preference) + return t.TunnelEncapSubTLV.Serialize(buf[:]) +} + +func (t *TunnelEncapSubTLVSRPreference) String() string { + return fmt.Sprintf("{Flags: 0x%02x, Preference: %d}", t.Flags, t.Preference) +} + +func (t *TunnelEncapSubTLVSRPreference) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Flags uint8 `json:"flags"` + Preference uint32 `json:"preference"` + }{ + Type: t.Type, + Flags: t.Flags, + Preference: t.Preference, + }) +} + +func NewTunnelEncapSubTLVSRPreference(flags uint32, preference uint32) *TunnelEncapSubTLVSRPreference { + return &TunnelEncapSubTLVSRPreference{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_SRPREFERENCE, + }, + Flags: uint8(flags), + Preference: preference, + } +} + +type TunnelEncapSubTLVSRPriority struct { + TunnelEncapSubTLV + Priority uint8 +} + +func (t *TunnelEncapSubTLVSRPriority) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + // Second byte carries the length of SR Preference SubTLV + if t.Length != 2 { + msg := fmt.Sprintf("Invalid TunnelEncapSubTLVSRPriority length: %d", t.Length) + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg) + } + t.Priority = value[0] + return nil +} + +func (t *TunnelEncapSubTLVSRPriority) Serialize() ([]byte, error) { + buf := make([]byte, t.Length) + buf[0] = t.Priority + return t.TunnelEncapSubTLV.Serialize(buf[:]) +} + +func (t *TunnelEncapSubTLVSRPriority) String() string { + return fmt.Sprintf("{Priority: %d}", t.Priority) +} + +func (t *TunnelEncapSubTLVSRPriority) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Priority uint8 `json:"priority"` + }{ + Type: t.Type, + Priority: t.Priority, + }) +} + +func NewTunnelEncapSubTLVSRPriority(priority uint8) *TunnelEncapSubTLVSRPriority { + return &TunnelEncapSubTLVSRPriority{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_SRPRIORITY, + }, + Priority: priority, + } +} + +type TunnelEncapSubTLVSRPolicyName struct { + TunnelEncapSubTLV + PolicyName string +} + +func (t *TunnelEncapSubTLVSRPolicyName) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + // Skip Reserved byte + t.PolicyName = string(value[1:t.TunnelEncapSubTLV.Len()]) + return nil +} + +func (t *TunnelEncapSubTLVSRPolicyName) Serialize() ([]byte, error) { + buf := make([]byte, t.Length) + copy(buf[1:], t.PolicyName) + return t.TunnelEncapSubTLV.Serialize(buf[:]) +} + +func (t *TunnelEncapSubTLVSRPolicyName) String() string { + return fmt.Sprintf("{Policy Name: %s}", t.PolicyName) +} + +func (t *TunnelEncapSubTLVSRPolicyName) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + PolicyName string `json:"policy_name"` + }{ + Type: t.Type, + PolicyName: t.PolicyName, + }) +} + +func NewTunnelEncapSubTLVSRPolicyName(pn string) *TunnelEncapSubTLVSRPolicyName { + return &TunnelEncapSubTLVSRPolicyName{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_SRPOLICY_NAME, + }, + PolicyName: pn, + } +} + +type SRENLPValue uint8 + +const ( + // ENLPType1 Indicates to push an IPv4 Explicit NULL label on an unlabeled IPv4 + // packet, but do not push an IPv6 Explicit NULL label on an + // unlabeled IPv6 packet. + ENLPType1 SRENLPValue = 1 + // ENLPType2 Indicates to push an IPv6 Explicit NULL label on an unlabeled IPv6 + // packet, but do not push an IPv4 Explicit NULL label on an + // unlabeled IPv4 packet. + ENLPType2 SRENLPValue = 2 + // ENLPType3 Indicates to push an IPv4 Explicit NULL label on an unlabeled IPv4 + // packet, and push an IPv6 Explicit NULL label on an unlabeled + // IPv6 packet. + ENLPType3 SRENLPValue = 3 + // ENLPType4 Indicates to not push an Explicit NULL label. + ENLPType4 SRENLPValue = 4 +) + +type TunnelEncapSubTLVSRENLP struct { + TunnelEncapSubTLV + Flags uint8 + ENLP SRENLPValue +} + +func (t *TunnelEncapSubTLVSRENLP) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return err + } + // Second byte carries the length of SR Preference SubTLV + if t.Length != 3 { + msg := fmt.Sprintf("Invalid TunnelEncapSubTLVSRENLP length: %d", t.Length) + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg) + } + t.Flags = value[0] + switch SRENLPValue(value[2]) { + case ENLPType1: + case ENLPType2: + case ENLPType3: + case ENLPType4: + default: + msg := fmt.Sprintf("Invalid ENLP Type: %d", value[2]) + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg) + } + t.ENLP = SRENLPValue(value[2]) + return nil +} + +func (t *TunnelEncapSubTLVSRENLP) Serialize() ([]byte, error) { + buf := make([]byte, t.Length) + buf[0] = t.Flags + buf[2] = byte(t.ENLP) + return t.TunnelEncapSubTLV.Serialize(buf[:]) +} + +func (t *TunnelEncapSubTLVSRENLP) String() string { + return fmt.Sprintf("{Flags: 0x%02x, ENLP Type: %d}", t.Flags, t.ENLP) +} + +func (t *TunnelEncapSubTLVSRENLP) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Flags uint8 `json:"flags"` + ENLP uint8 `json:"enlp"` + }{ + Type: t.Type, + Flags: t.Flags, + ENLP: uint8(t.ENLP), + }) +} + +func NewTTunnelEncapSubTLVSRENLP(flags uint32, enlp SRENLPValue) *TunnelEncapSubTLVSRENLP { + return &TunnelEncapSubTLVSRENLP{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_SRENLP, + }, + Flags: uint8(flags), + ENLP: enlp, + } +} + +type BSID struct { + Length int + Value []byte +} + +func (b *BSID) String() string { + switch b.Length { + case 0: + return "n/a" + case 4: + bsid := binary.BigEndian.Uint32(b.Value) + bsid >>= 12 + return strconv.Itoa(int(bsid)) + case 16: + return net.IP(b.Value).To16().String() + default: + return "invalid" + } +} + +func (b *BSID) Serialize() []byte { + return []byte{} +} +func NewBSID(v []byte, l int) (*BSID, error) { + switch l { + case 0: + case 4: + case 16: + default: + return nil, fmt.Errorf("invalid length %d", l) + } + if l < len(v) { + return nil, fmt.Errorf("parameter length does not match the length of data bytes") + } + bsid := &BSID{ + Length: l, + Value: make([]byte, l), + } + copy(bsid.Value, v) + + return bsid, nil +} + +type TunnelEncapSubTLVSRBSID struct { + TunnelEncapSubTLV + Flags uint8 + BSID *BSID +} + +func (t *TunnelEncapSubTLVSRBSID) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error()) + } + // Check Sub TLV length, only 3 possible length are allowed + switch t.Length { + case 2: + case 6: + case 18: + default: + msg := fmt.Sprintf("Invalid TunnelEncapSubTLVSRBSID length: %d", t.Length) + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg) + } + t.Flags = value[0] + t.BSID, err = NewBSID(value[2:t.Length], int(t.Length-2)) + if err != nil { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error()) + } + return nil +} + +func (t *TunnelEncapSubTLVSRBSID) Serialize() ([]byte, error) { + buf := make([]byte, t.Length) + buf[0] = t.Flags + copy(buf[2:t.BSID.Length], t.BSID.Serialize()) + return t.TunnelEncapSubTLV.Serialize(buf[:]) +} + +func (t *TunnelEncapSubTLVSRBSID) String() string { + return fmt.Sprintf("{S-Flag: %t, I-Flag: %t, BSID: %s}", t.Flags&0x80 == 0x80, t.Flags&0x40 == 0x40, t.BSID.String()) +} + +func (t *TunnelEncapSubTLVSRBSID) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Flags uint8 `json:"flags"` + BSID string `json:"binding_sid,omitempty"` + }{ + Type: t.Type, + Flags: t.Flags, + BSID: t.BSID.String(), + }) +} + +// TODO sbezverk Figure out parameters to pass to NewTunnelEncapSubTLVSRBSID +func NewTunnelEncapSubTLVSRBSID(flags uint32) *TunnelEncapSubTLVSRBSID { + return &TunnelEncapSubTLVSRBSID{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_SRBINDING_SID, + }, + Flags: uint8(flags), + } +} + +// SegmentType defines a type of Segment in Segment List +type SegmentType int + +const ( + // TypeA Segment Sub-TLV encodes a single SR-MPLS SID + TypeA SegmentType = 1 + // TypeC Segment Sub-TLV encodes an IPv4 node address, SR Algorithm + // and an optional SR-MPLS SID + TypeC SegmentType = 3 + // TypeD Segment Sub-TLV encodes an IPv6 node address, SR Algorithm + // and an optional SR-MPLS SID. + TypeD SegmentType = 4 + // TypeE Segment Sub-TLV encodes an IPv4 node address, a local + // interface Identifier (Local Interface ID) and an optional SR-MPLS + // SID. + TypeE SegmentType = 5 + // TypeF Segment Sub-TLV encodes an adjacency local address, an + // adjacency remote address and an optional SR-MPLS SID. + TypeF SegmentType = 6 + // TypeG Segment Sub-TLV encodes an IPv6 Link Local adjacency with + // IPv6 local node address, a local interface identifier (Local + // Interface ID), IPv6 remote node address , a remote interface + // identifier (Remote Interface ID) and an optional SR-MPLS SID. + TypeG SegmentType = 7 + // TypeH Segment Sub-TLV encodes an adjacency local address, an + // adjacency remote address and an optional SR-MPLS SID. + TypeH SegmentType = 8 +) + +const SegmentListWeightType = 9 + +// Weight sub-TLV specifies the weight associated to a given segment list. +type SegmentListWeight struct { + TunnelEncapSubTLV + Flags uint8 + Weight uint32 +} + +func (s *SegmentListWeight) DecodeFromBytes(data []byte) error { + value, err := s.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error()) + } + s.Flags = value[0] + s.Weight = binary.BigEndian.Uint32(value[2:6]) + return nil +} +func (s *SegmentListWeight) Serialize() ([]byte, error) { + buf := make([]byte, 6) + buf[0] = s.Flags + binary.BigEndian.PutUint32(buf[2:6], s.Weight) + return s.TunnelEncapSubTLV.Serialize(buf) +} +func (s *SegmentListWeight) String() string { + return fmt.Sprintf("{Flags: 0x%02x, Weight: %d}", s.Flags, s.Weight) +} + +func (s *SegmentListWeight) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Flags uint8 `json:"flags"` + Weight uint32 `json:"weight,omitempty"` + }{ + Type: s.Type, + Flags: s.Flags, + Weight: s.Weight, + }) +} + +type SegmentTypeA struct { + TunnelEncapSubTLV + Flags uint8 + Label uint32 +} + +func (s *SegmentTypeA) DecodeFromBytes(data []byte) error { + value, err := s.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error()) + } + s.Flags = value[0] + s.Label = binary.BigEndian.Uint32(value[2:6]) + return nil +} +func (s *SegmentTypeA) Serialize() ([]byte, error) { + buf := make([]byte, 6) + buf[0] = s.Flags + binary.BigEndian.PutUint32(buf[2:6], s.Label) + return s.TunnelEncapSubTLV.Serialize(buf) +} +func (s *SegmentTypeA) String() string { + + return fmt.Sprintf("{V-flag: %t, A-flag:, %t S-flag: %t, B-flag: %t, Label: %d TC: %d S: %t TTL: %d}", + s.Flags&0x80 == 0x80, s.Flags&0x40 == 0x40, s.Flags&0x20 == 0x20, s.Flags&0x10 == 0x10, + s.Label>>12, s.Label&0x00000e00>>9, s.Label&0x00000100 == 0x00000100, s.Label&0x000000ff) +} + +func (s *SegmentTypeA) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + VFlag bool `json:"v_flag"` + AFlag bool `json:"a_flag"` + SFlag bool `json:"s_flag"` + BFlag bool `json:"b_flag"` + Label uint32 `json:"label"` + TC uint8 `json:"tc"` + S bool `json:"s"` + TTL uint8 `json:"ttl"` + }{ + Type: s.Type, + VFlag: s.Flags&0x80 == 0x80, + AFlag: s.Flags&0x40 == 0x40, + SFlag: s.Flags&0x20 == 0x20, + BFlag: s.Flags&0x10 == 0x10, + Label: s.Label >> 12, + TC: uint8(s.Label & 0x00000e00 >> 9), + S: s.Label&0x00000100 == 0x00000100, + TTL: uint8(s.Label & 0x000000ff), + }) +} + +type TunnelEncapSubTLVSRSegmentList struct { + TunnelEncapSubTLV + Weight *SegmentListWeight + Segments []TunnelEncapSubTLVInterface +} + +func (t *TunnelEncapSubTLVSRSegmentList) DecodeFromBytes(data []byte) error { + value, err := t.TunnelEncapSubTLV.DecodeFromBytes(data) + if err != nil { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error()) + } + // Skip reserved byte to access inner SubTLV type + value = value[1:] + t.Segments = make([]TunnelEncapSubTLVInterface, 0) + p := 0 + for p < t.TunnelEncapSubTLV.Len()-4 { + var segment TunnelEncapSubTLVInterface + switch SegmentType(value[0]) { + case SegmentListWeightType: + t.Weight = &SegmentListWeight{} + if err := t.Weight.DecodeFromBytes(value); err != nil { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error()) + } + p += t.Weight.TunnelEncapSubTLV.Len() + value = value[t.Weight.TunnelEncapSubTLV.Len():] + continue + case TypeA: + segment = &SegmentTypeA{} + if err := segment.DecodeFromBytes(value); err != nil { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, err.Error()) + } + case TypeC: + fallthrough + case TypeD: + fallthrough + case TypeE: + fallthrough + case TypeF: + fallthrough + case TypeG: + fallthrough + case TypeH: + msg := fmt.Sprintf("Invalid SR Policy Segment SubTLV %d is not yet supported", value[0]) + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg) + default: + msg := fmt.Sprintf("Invalid SR Policy Segment List SubTLV %d", value[0]) + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, msg) + } + t.Segments = append(t.Segments, segment) + p += segment.Len() + value = value[segment.Len():] + } + return nil +} + +func (t *TunnelEncapSubTLVSRSegmentList) Serialize() ([]byte, error) { + buf := make([]byte, t.Length) + wbuf, err := t.Weight.Serialize() + if err != nil { + return nil, err + } + p := 0 + // Add reserved byte + p++ + copy(buf[p:], wbuf) + p += len(wbuf) + for _, s := range t.Segments { + sbuf, err := s.Serialize() + if err != nil { + return nil, err + } + copy(buf[p:], sbuf) + p += len(sbuf) + } + return t.TunnelEncapSubTLV.Serialize(buf[:]) +} + +func (t *TunnelEncapSubTLVSRSegmentList) String() string { + var segments string + for _, s := range t.Segments { + segments += s.String() + } + return fmt.Sprintf("{Weight: %s Segment List: %s}", t.Weight.String(), segments) +} + +func (t *TunnelEncapSubTLVSRSegmentList) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type EncapSubTLVType `json:"type"` + Weight *SegmentListWeight + Segments []TunnelEncapSubTLVInterface + }{ + Type: t.Type, + Weight: t.Weight, + Segments: t.Segments, + }) +} + +func NewTunnelEncapSubTLVSRSegmentList() *TunnelEncapSubTLVSRSegmentList { + return &TunnelEncapSubTLVSRSegmentList{ + TunnelEncapSubTLV: TunnelEncapSubTLV{ + Type: ENCAP_SUBTLV_TYPE_SRSEGMENT_LIST, + }, + } +} diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang index eeda0aa6..e00e1c41 100644 --- a/tools/pyang_plugins/gobgp.yang +++ b/tools/pyang_plugins/gobgp.yang @@ -141,6 +141,20 @@ module gobgp { reference "draft-ietf-idr-flowspec-l2vpn-03"; } + identity IPV4-SRPOLICY { + base bgp-types:afi-safi-type; + description + "SR Policy IPv4 (AFI,SAFI = 1,73)"; + reference "https://tools.ietf.org/html/draft-ietf-idr-segment-routing-te-policy-11"; + } + + identity IPV6-SRPOLICY { + base bgp-types:afi-safi-type; + description + "SR Policy IPv6 (AFI,SAFI = 2,73)"; + reference "https://tools.ietf.org/html/draft-ietf-idr-segment-routing-te-policy-11"; + } + identity OPAQUE { base bgp-types:afi-safi-type; description |