diff options
-rw-r--r-- | api/gobgp.pb.go | 62 | ||||
-rw-r--r-- | api/gobgp.proto | 20 | ||||
-rw-r--r-- | gobgp/neighbor.go | 12 | ||||
-rw-r--r-- | packet/bgp.go | 115 |
4 files changed, 207 insertions, 2 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index 0b6689dd..cc2f5a4a 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -25,6 +25,7 @@ It has these top-level messages: Nlri TunnelEncapSubTLV TunnelEncapTLV + PmsiTunnel PathAttr AsPath Path @@ -347,6 +348,44 @@ func (x TUNNEL_TYPE) String() string { return proto.EnumName(TUNNEL_TYPE_name, int32(x)) } +type PMSI_TUNNEL_TYPE int32 + +const ( + PMSI_TUNNEL_TYPE_NO_TUNNEL PMSI_TUNNEL_TYPE = 0 + PMSI_TUNNEL_TYPE_RSVP_TE_P2MP PMSI_TUNNEL_TYPE = 1 + PMSI_TUNNEL_TYPE_MLDP_P2MP PMSI_TUNNEL_TYPE = 2 + PMSI_TUNNEL_TYPE_PIM_SSM_TREE PMSI_TUNNEL_TYPE = 3 + PMSI_TUNNEL_TYPE_PIM_SM_TREE PMSI_TUNNEL_TYPE = 4 + PMSI_TUNNEL_TYPE_BIDIR_PIM_TREE PMSI_TUNNEL_TYPE = 5 + PMSI_TUNNEL_TYPE_INGRESS_REPL PMSI_TUNNEL_TYPE = 6 + PMSI_TUNNEL_TYPE_MLDP_MP2MP PMSI_TUNNEL_TYPE = 7 +) + +var PMSI_TUNNEL_TYPE_name = map[int32]string{ + 0: "NO_TUNNEL", + 1: "RSVP_TE_P2MP", + 2: "MLDP_P2MP", + 3: "PIM_SSM_TREE", + 4: "PIM_SM_TREE", + 5: "BIDIR_PIM_TREE", + 6: "INGRESS_REPL", + 7: "MLDP_MP2MP", +} +var PMSI_TUNNEL_TYPE_value = map[string]int32{ + "NO_TUNNEL": 0, + "RSVP_TE_P2MP": 1, + "MLDP_P2MP": 2, + "PIM_SSM_TREE": 3, + "PIM_SM_TREE": 4, + "BIDIR_PIM_TREE": 5, + "INGRESS_REPL": 6, + "MLDP_MP2MP": 7, +} + +func (x PMSI_TUNNEL_TYPE) String() string { + return proto.EnumName(PMSI_TUNNEL_TYPE_name, int32(x)) +} + type EVPN_TYPE int32 const ( @@ -421,6 +460,7 @@ const ( BGP_ATTR_TYPE_EXTENDED_COMMUNITIES BGP_ATTR_TYPE = 16 BGP_ATTR_TYPE_AS4_PATH BGP_ATTR_TYPE = 17 BGP_ATTR_TYPE_AS4_AGGREGATOR BGP_ATTR_TYPE = 18 + BGP_ATTR_TYPE_PMSI_TUNNEL BGP_ATTR_TYPE = 22 BGP_ATTR_TYPE_TUNNEL_ENCAP BGP_ATTR_TYPE = 23 ) @@ -441,6 +481,7 @@ var BGP_ATTR_TYPE_name = map[int32]string{ 16: "EXTENDED_COMMUNITIES", 17: "AS4_PATH", 18: "AS4_AGGREGATOR", + 22: "PMSI_TUNNEL", 23: "TUNNEL_ENCAP", } var BGP_ATTR_TYPE_value = map[string]int32{ @@ -460,6 +501,7 @@ var BGP_ATTR_TYPE_value = map[string]int32{ "EXTENDED_COMMUNITIES": 16, "AS4_PATH": 17, "AS4_AGGREGATOR": 18, + "PMSI_TUNNEL": 22, "TUNNEL_ENCAP": 23, } @@ -756,6 +798,17 @@ func (m *TunnelEncapTLV) GetSubTlv() []*TunnelEncapSubTLV { return nil } +type PmsiTunnel struct { + IsLeafInfoRequired bool `protobuf:"varint,1,opt,name=is_leaf_info_required" json:"is_leaf_info_required,omitempty"` + Type PMSI_TUNNEL_TYPE `protobuf:"varint,2,opt,name=type,enum=api.PMSI_TUNNEL_TYPE" json:"type,omitempty"` + Label uint32 `protobuf:"varint,3,opt,name=label" json:"label,omitempty"` + TunnelId string `protobuf:"bytes,4,opt,name=tunnel_id" json:"tunnel_id,omitempty"` +} + +func (m *PmsiTunnel) Reset() { *m = PmsiTunnel{} } +func (m *PmsiTunnel) String() string { return proto.CompactTextString(m) } +func (*PmsiTunnel) ProtoMessage() {} + type PathAttr struct { Type BGP_ATTR_TYPE `protobuf:"varint,1,opt,name=type,enum=api.BGP_ATTR_TYPE" json:"type,omitempty"` Value []string `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` @@ -770,6 +823,7 @@ type PathAttr struct { Cluster []string `protobuf:"bytes,11,rep,name=cluster" json:"cluster,omitempty"` Nlri []*Nlri `protobuf:"bytes,12,rep,name=nlri" json:"nlri,omitempty"` TunnelEncap []*TunnelEncapTLV `protobuf:"bytes,13,rep,name=tunnel_encap" json:"tunnel_encap,omitempty"` + PmsiTunnel *PmsiTunnel `protobuf:"bytes,14,opt,name=pmsi_tunnel" json:"pmsi_tunnel,omitempty"` } func (m *PathAttr) Reset() { *m = PathAttr{} } @@ -804,6 +858,13 @@ func (m *PathAttr) GetTunnelEncap() []*TunnelEncapTLV { return nil } +func (m *PathAttr) GetPmsiTunnel() *PmsiTunnel { + if m != nil { + return m.PmsiTunnel + } + return nil +} + type AsPath struct { SegmentType uint32 `protobuf:"varint,1,opt,name=segment_type" json:"segment_type,omitempty"` Asns []uint32 `protobuf:"varint,2,rep,name=asns" json:"asns,omitempty"` @@ -1169,6 +1230,7 @@ func init() { proto.RegisterEnum("api.EXTENDED_COMMUNITIE_TYPE", EXTENDED_COMMUNITIE_TYPE_name, EXTENDED_COMMUNITIE_TYPE_value) proto.RegisterEnum("api.EXTENDED_COMMUNITIE_SUBTYPE", EXTENDED_COMMUNITIE_SUBTYPE_name, EXTENDED_COMMUNITIE_SUBTYPE_value) proto.RegisterEnum("api.TUNNEL_TYPE", TUNNEL_TYPE_name, TUNNEL_TYPE_value) + proto.RegisterEnum("api.PMSI_TUNNEL_TYPE", PMSI_TUNNEL_TYPE_name, PMSI_TUNNEL_TYPE_value) proto.RegisterEnum("api.EVPN_TYPE", EVPN_TYPE_name, EVPN_TYPE_value) proto.RegisterEnum("api.ENCAP_SUBTLV_TYPE", ENCAP_SUBTLV_TYPE_name, ENCAP_SUBTLV_TYPE_value) proto.RegisterEnum("api.BGP_ATTR_TYPE", BGP_ATTR_TYPE_name, BGP_ATTR_TYPE_value) diff --git a/api/gobgp.proto b/api/gobgp.proto index 2c6c70d5..dce05d8b 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -187,6 +187,17 @@ enum TUNNEL_TYPE { VXLAN_GRE = 12; } +enum PMSI_TUNNEL_TYPE { + NO_TUNNEL = 0; + RSVP_TE_P2MP = 1; + MLDP_P2MP = 2; + PIM_SSM_TREE = 3; + PIM_SM_TREE = 4; + BIDIR_PIM_TREE = 5; + INGRESS_REPL = 6; + MLDP_MP2MP = 7; +} + enum EVPN_TYPE { UNKNOWN_EVPN_TYPE = 0; ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY = 1; @@ -249,6 +260,13 @@ message TunnelEncapTLV { repeated TunnelEncapSubTLV sub_tlv = 2; } +message PmsiTunnel { + bool is_leaf_info_required = 1; + PMSI_TUNNEL_TYPE type = 2; + uint32 label = 3; + string tunnel_id = 4; +} + enum BGP_ATTR_TYPE { UNKNOWN_ATTR = 0; ORIGIN = 1; @@ -266,6 +284,7 @@ enum BGP_ATTR_TYPE { EXTENDED_COMMUNITIES = 16; AS4_PATH = 17; AS4_AGGREGATOR = 18; + PMSI_TUNNEL = 22; TUNNEL_ENCAP = 23; } @@ -283,6 +302,7 @@ message PathAttr { repeated string cluster = 11; repeated Nlri nlri = 12; repeated TunnelEncapTLV tunnel_encap = 13; + PmsiTunnel pmsi_tunnel = 14; } message AsPath { diff --git a/gobgp/neighbor.go b/gobgp/neighbor.go index a3d8c27b..9935d1a0 100644 --- a/gobgp/neighbor.go +++ b/gobgp/neighbor.go @@ -305,6 +305,18 @@ func showRoute(pathList []*api.Path, showAge bool, showBest bool, isMonitor bool s = append(s, fmt.Sprintf("{Originator: %v}", a.Originator)) case api.BGP_ATTR_TYPE_CLUSTER_LIST: s = append(s, fmt.Sprintf("{Cluster: %v}", a.Cluster)) + case api.BGP_ATTR_TYPE_PMSI_TUNNEL: + info := a.PmsiTunnel + s1 := bytes.NewBuffer(make([]byte, 0, 64)) + s1.WriteString(fmt.Sprintf("{PMSI Tunnel: {Type: %s, ID: %s", info.Type, info.TunnelId)) + if info.Label > 0 { + s1.WriteString(fmt.Sprintf(", Label: %d", info.Label)) + } + if info.IsLeafInfoRequired { + s1.WriteString(fmt.Sprintf(", Leaf Info Required")) + } + s1.WriteString("}}") + s = append(s, s1.String()) case api.BGP_ATTR_TYPE_TUNNEL_ENCAP: s1 := bytes.NewBuffer(make([]byte, 0, 64)) s1.WriteString("{Encap: ") diff --git a/packet/bgp.go b/packet/bgp.go index f5afc948..0c345ed2 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -134,6 +134,19 @@ const ( TUNNEL_TYPE_VXLAN_GRE TunnelType = 12 ) +type PmsiTunnelType uint8 + +const ( + PMSI_TUNNEL_TYPE_NO_TUNNEL PmsiTunnelType = 0 + PMSI_TUNNEL_TYPE_RSVP_TE_P2MP PmsiTunnelType = 1 + PMSI_TUNNEL_TYPE_MLDP_P2MP PmsiTunnelType = 2 + PMSI_TUNNEL_TYPE_PIM_SSM_TREE PmsiTunnelType = 3 + PMSI_TUNNEL_TYPE_PIM_SM_TREE PmsiTunnelType = 4 + PMSI_TUNNEL_TYPE_BIDIR_PIM_TREE PmsiTunnelType = 5 + PMSI_TUNNEL_TYPE_INGRESS_REPL PmsiTunnelType = 6 + PMSI_TUNNEL_TYPE_MLDP_MP2MP PmsiTunnelType = 7 +) + type EncapSubTLVType uint8 const ( @@ -1765,8 +1778,8 @@ const ( _ _ _ - _ - BGP_ATTR_TYPE_TUNNEL_ENCAP // = 23 + BGP_ATTR_TYPE_PMSI_TUNNEL // = 22 + BGP_ATTR_TYPE_TUNNEL_ENCAP ) // NOTIFICATION Error Code RFC 4271 4.5. @@ -1856,6 +1869,7 @@ var pathAttrFlags map[BGPAttrType]BGPAttrFlag = map[BGPAttrType]BGPAttrFlag{ BGP_ATTR_TYPE_EXTENDED_COMMUNITIES: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_TYPE_AS4_PATH: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_TYPE_AS4_AGGREGATOR: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_PMSI_TUNNEL: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_TYPE_TUNNEL_ENCAP: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, } @@ -3666,6 +3680,101 @@ func NewPathAttributeTunnelEncap(value []*TunnelEncapTLV) *PathAttributeTunnelEn } } +type PmsiTunnelIDInterface interface { + Serialize() ([]byte, error) + String() string +} + +type DefaultPmsiTunnelID struct { + Value []byte +} + +func (i *DefaultPmsiTunnelID) Serialize() ([]byte, error) { + return i.Value, nil +} + +func (i *DefaultPmsiTunnelID) String() string { + return string(i.Value) +} + +type IngressReplTunnelID struct { + Value net.IP +} + +func (i *IngressReplTunnelID) Serialize() ([]byte, error) { + if i.Value.To4() != nil { + return []byte(i.Value.To4()), nil + } + return []byte(i.Value), nil +} + +func (i *IngressReplTunnelID) String() string { + return i.Value.String() +} + +type PathAttributePmsiTunnel struct { + PathAttribute + IsLeafInfoRequired bool + TunnelType PmsiTunnelType + Label uint32 + TunnelID PmsiTunnelIDInterface +} + +func (p *PathAttributePmsiTunnel) DecodeFromBytes(data []byte) error { + err := p.PathAttribute.DecodeFromBytes(data) + if err != nil { + return err + } + if len(p.PathAttribute.Value) < 5 { + eCode := uint8(BGP_ERROR_UPDATE_MESSAGE_ERROR) + eSubCode := uint8(BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST) + return NewMessageError(eCode, eSubCode, nil, "PMSI Tunnel length is incorrect") + } + + if (p.PathAttribute.Value[0] & 0x01) > 0 { + p.IsLeafInfoRequired = true + } + p.TunnelType = PmsiTunnelType(p.PathAttribute.Value[1]) + p.Label = labelDecode(p.PathAttribute.Value[2:5]) + + switch p.TunnelType { + case PMSI_TUNNEL_TYPE_INGRESS_REPL: + p.TunnelID = &IngressReplTunnelID{net.IP(p.PathAttribute.Value[5:])} + default: + p.TunnelID = &DefaultPmsiTunnelID{p.PathAttribute.Value[5:]} + } + return nil +} + +func (p *PathAttributePmsiTunnel) Serialize() ([]byte, error) { + buf := make([]byte, 2) + if p.IsLeafInfoRequired { + buf[0] = 0x01 + } + buf[1] = byte(p.TunnelType) + lbuf := make([]byte, 3) + labelSerialize(p.Label, lbuf) + buf = append(buf, lbuf...) + ibuf, err := p.TunnelID.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, ibuf...) + return buf, nil +} + +func (p *PathAttributePmsiTunnel) ToApiStruct() *api.PathAttr { + return &api.PathAttr{ + Type: api.BGP_ATTR_TYPE_PMSI_TUNNEL, + PmsiTunnel: &api.PmsiTunnel{ + IsLeafInfoRequired: p.IsLeafInfoRequired, + Type: api.PMSI_TUNNEL_TYPE(p.TunnelType), + Label: p.Label, + TunnelId: p.TunnelID.String(), + }, + } +} + type PathAttributeUnknown struct { PathAttribute } @@ -3720,6 +3829,8 @@ func GetPathAttribute(data []byte) (PathAttributeInterface, error) { return &PathAttributeAs4Aggregator{}, nil case BGP_ATTR_TYPE_TUNNEL_ENCAP: return &PathAttributeTunnelEncap{}, nil + case BGP_ATTR_TYPE_PMSI_TUNNEL: + return &PathAttributePmsiTunnel{}, nil } return &PathAttributeUnknown{}, nil } |