summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSerguei Bezverkhi <sbezverk@cisco.com>2020-11-25 17:29:13 -0500
committerSerguei Bezverkhi <sbezverk@cisco.com>2020-11-25 17:29:13 -0500
commit48e55b7c388dd6912f4c7f39998723b4ab6159e3 (patch)
tree242bfba54e72ca8bc8cfbe0a77200b5b79e8c58e
parent66413b5335790dc9110b80c8cffe31b3259df9d2 (diff)
code changes
Signed-off-by: Serguei Bezverkhi <sbezverk@cisco.com>
-rw-r--r--internal/pkg/apiutil/attribute.go12
-rw-r--r--internal/pkg/config/bgp_configs.go18
-rw-r--r--pkg/packet/bgp/bgp.go183
-rw-r--r--pkg/packet/bgp/sr_policy.go721
-rw-r--r--tools/pyang_plugins/gobgp.yang14
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