diff options
-rw-r--r-- | api/gobgp.pb.go | 105 | ||||
-rw-r--r-- | api/gobgp.proto | 37 | ||||
-rw-r--r-- | api/util.go | 1 | ||||
-rw-r--r-- | packet/bgp.go | 93 |
4 files changed, 215 insertions, 21 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index b0f2ed40..af9dde83 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -14,8 +14,10 @@ It has these top-level messages: ModPathArguments AddressFamily Aggregator + ExtendedCommunity EVPNNlri EvpnMacIpAdvertisement + RTNlri Nlri TunnelEncapSubTLV TunnelEncapTLV @@ -106,7 +108,7 @@ const ( SAFI_EVPN SAFI = 70 SAFI_MPLS_VPN SAFI = 128 SAFI_MPLS_VPN_MULTICAST SAFI = 129 - SAFI_ROUTE_TARGET_CONSTRTAINS SAFI = 132 + SAFI_ROUTE_TARGET_CONSTRAINTS SAFI = 132 ) var SAFI_name = map[int32]string{ @@ -119,7 +121,7 @@ var SAFI_name = map[int32]string{ 70: "EVPN", 128: "MPLS_VPN", 129: "MPLS_VPN_MULTICAST", - 132: "ROUTE_TARGET_CONSTRTAINS", + 132: "ROUTE_TARGET_CONSTRAINTS", } var SAFI_value = map[string]int32{ "UNKNOWN_SAFI": 0, @@ -131,7 +133,7 @@ var SAFI_value = map[string]int32{ "EVPN": 70, "MPLS_VPN": 128, "MPLS_VPN_MULTICAST": 129, - "ROUTE_TARGET_CONSTRTAINS": 132, + "ROUTE_TARGET_CONSTRAINTS": 132, } func (x SAFI) String() string { @@ -161,6 +163,55 @@ func (x Origin) String() string { return proto.EnumName(Origin_name, int32(x)) } +type EXTENDED_COMMUNITIE_TYPE int32 + +const ( + EXTENDED_COMMUNITIE_TYPE_TWO_OCTET_AS_SPECIFIC EXTENDED_COMMUNITIE_TYPE = 0 + EXTENDED_COMMUNITIE_TYPE_IP4_SPECIFIC EXTENDED_COMMUNITIE_TYPE = 1 + EXTENDED_COMMUNITIE_TYPE_FOUR_OCTET_AS_SPECIFIC EXTENDED_COMMUNITIE_TYPE = 2 + EXTENDED_COMMUNITIE_TYPE_OPAQUE EXTENDED_COMMUNITIE_TYPE = 3 +) + +var EXTENDED_COMMUNITIE_TYPE_name = map[int32]string{ + 0: "TWO_OCTET_AS_SPECIFIC", + 1: "IP4_SPECIFIC", + 2: "FOUR_OCTET_AS_SPECIFIC", + 3: "OPAQUE", +} +var EXTENDED_COMMUNITIE_TYPE_value = map[string]int32{ + "TWO_OCTET_AS_SPECIFIC": 0, + "IP4_SPECIFIC": 1, + "FOUR_OCTET_AS_SPECIFIC": 2, + "OPAQUE": 3, +} + +func (x EXTENDED_COMMUNITIE_TYPE) String() string { + return proto.EnumName(EXTENDED_COMMUNITIE_TYPE_name, int32(x)) +} + +type EXTENDED_COMMUNITIE_SUBTYPE int32 + +const ( + EXTENDED_COMMUNITIE_SUBTYPE_ORIGIN_VALIDATION EXTENDED_COMMUNITIE_SUBTYPE = 0 + EXTENDED_COMMUNITIE_SUBTYPE_ROUTE_TARGET EXTENDED_COMMUNITIE_SUBTYPE = 2 + EXTENDED_COMMUNITIE_SUBTYPE_ROUTE_ORIGIN EXTENDED_COMMUNITIE_SUBTYPE = 3 +) + +var EXTENDED_COMMUNITIE_SUBTYPE_name = map[int32]string{ + 0: "ORIGIN_VALIDATION", + 2: "ROUTE_TARGET", + 3: "ROUTE_ORIGIN", +} +var EXTENDED_COMMUNITIE_SUBTYPE_value = map[string]int32{ + "ORIGIN_VALIDATION": 0, + "ROUTE_TARGET": 2, + "ROUTE_ORIGIN": 3, +} + +func (x EXTENDED_COMMUNITIE_SUBTYPE) String() string { + return proto.EnumName(EXTENDED_COMMUNITIE_SUBTYPE_name, int32(x)) +} + type TUNNEL_TYPE int32 const ( @@ -402,6 +453,19 @@ func (m *Aggregator) Reset() { *m = Aggregator{} } func (m *Aggregator) String() string { return proto.CompactTextString(m) } func (*Aggregator) ProtoMessage() {} +type ExtendedCommunity struct { + Type EXTENDED_COMMUNITIE_TYPE `protobuf:"varint,1,opt,name=type,enum=api.EXTENDED_COMMUNITIE_TYPE" json:"type,omitempty"` + Subtype EXTENDED_COMMUNITIE_SUBTYPE `protobuf:"varint,2,opt,name=subtype,enum=api.EXTENDED_COMMUNITIE_SUBTYPE" json:"subtype,omitempty"` + IsTransitive bool `protobuf:"varint,3,opt,name=is_transitive" json:"is_transitive,omitempty"` + Asn uint32 `protobuf:"varint,4,opt,name=asn" json:"asn,omitempty"` + Ipv4 string `protobuf:"bytes,5,opt,name=ipv4" json:"ipv4,omitempty"` + LocalAdmin uint32 `protobuf:"varint,6,opt,name=local_admin" json:"local_admin,omitempty"` +} + +func (m *ExtendedCommunity) Reset() { *m = ExtendedCommunity{} } +func (m *ExtendedCommunity) String() string { return proto.CompactTextString(m) } +func (*ExtendedCommunity) ProtoMessage() {} + type EVPNNlri struct { Type EVPN_TYPE `protobuf:"varint,1,opt,name=type,enum=api.EVPN_TYPE" json:"type,omitempty"` // EvpnAutoDiscoveryRoute = 2; @@ -434,11 +498,29 @@ func (m *EvpnMacIpAdvertisement) Reset() { *m = EvpnMacIpAdvertisement{} func (m *EvpnMacIpAdvertisement) String() string { return proto.CompactTextString(m) } func (*EvpnMacIpAdvertisement) ProtoMessage() {} +type RTNlri struct { + Asn uint32 `protobuf:"varint,1,opt,name=asn" json:"asn,omitempty"` + Target *ExtendedCommunity `protobuf:"bytes,2,opt,name=target" json:"target,omitempty"` + Length uint32 `protobuf:"varint,3,opt,name=length" json:"length,omitempty"` +} + +func (m *RTNlri) Reset() { *m = RTNlri{} } +func (m *RTNlri) String() string { return proto.CompactTextString(m) } +func (*RTNlri) ProtoMessage() {} + +func (m *RTNlri) GetTarget() *ExtendedCommunity { + if m != nil { + return m.Target + } + return nil +} + type Nlri struct { Af *AddressFamily `protobuf:"bytes,1,opt,name=af" json:"af,omitempty"` Prefix string `protobuf:"bytes,2,opt,name=prefix" json:"prefix,omitempty"` - EvpnNlri *EVPNNlri `protobuf:"bytes,3,opt,name=evpn_nlri" json:"evpn_nlri,omitempty"` - Nexthop string `protobuf:"bytes,4,opt,name=nexthop" json:"nexthop,omitempty"` + Nexthop string `protobuf:"bytes,3,opt,name=nexthop" json:"nexthop,omitempty"` + EvpnNlri *EVPNNlri `protobuf:"bytes,4,opt,name=evpn_nlri" json:"evpn_nlri,omitempty"` + RtNlri *RTNlri `protobuf:"bytes,5,opt,name=rt_nlri" json:"rt_nlri,omitempty"` } func (m *Nlri) Reset() { *m = Nlri{} } @@ -459,6 +541,13 @@ func (m *Nlri) GetEvpnNlri() *EVPNNlri { return nil } +func (m *Nlri) GetRtNlri() *RTNlri { + if m != nil { + return m.RtNlri + } + return nil +} + type TunnelEncapSubTLV struct { Type ENCAP_SUBTLV_TYPE `protobuf:"varint,1,opt,name=type,enum=api.ENCAP_SUBTLV_TYPE" json:"type,omitempty"` Value string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` @@ -500,7 +589,7 @@ type PathAttr struct { Communites []uint32 `protobuf:"varint,9,rep,name=communites" json:"communites,omitempty"` Originator string `protobuf:"bytes,10,opt,name=originator" json:"originator,omitempty"` Cluster []string `protobuf:"bytes,11,rep,name=cluster" json:"cluster,omitempty"` - Nlri *Nlri `protobuf:"bytes,12,opt,name=nlri" json:"nlri,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"` } @@ -515,7 +604,7 @@ func (m *PathAttr) GetAggregator() *Aggregator { return nil } -func (m *PathAttr) GetNlri() *Nlri { +func (m *PathAttr) GetNlri() []*Nlri { if m != nil { return m.Nlri } @@ -647,6 +736,8 @@ func init() { proto.RegisterEnum("api.AFI", AFI_name, AFI_value) proto.RegisterEnum("api.SAFI", SAFI_name, SAFI_value) proto.RegisterEnum("api.Origin", Origin_name, Origin_value) + 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.EVPN_TYPE", EVPN_TYPE_name, EVPN_TYPE_value) proto.RegisterEnum("api.ENCAP_SUBTLV_TYPE", ENCAP_SUBTLV_TYPE_name, ENCAP_SUBTLV_TYPE_value) diff --git a/api/gobgp.proto b/api/gobgp.proto index 611f1abc..7f12d27b 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -78,7 +78,7 @@ enum SAFI { EVPN = 70; MPLS_VPN = 128; MPLS_VPN_MULTICAST = 129; - ROUTE_TARGET_CONSTRTAINS = 132; + ROUTE_TARGET_CONSTRAINTS = 132; } message AddressFamily { @@ -97,6 +97,28 @@ message Aggregator { string address = 2; } +enum EXTENDED_COMMUNITIE_TYPE { + TWO_OCTET_AS_SPECIFIC = 0; + IP4_SPECIFIC = 1; + FOUR_OCTET_AS_SPECIFIC = 2; + OPAQUE = 3; +} + +enum EXTENDED_COMMUNITIE_SUBTYPE { + ORIGIN_VALIDATION = 0; + ROUTE_TARGET = 2; + ROUTE_ORIGIN = 3; +} + +message ExtendedCommunity { + EXTENDED_COMMUNITIE_TYPE type = 1; + EXTENDED_COMMUNITIE_SUBTYPE subtype = 2; + bool is_transitive = 3; + uint32 asn = 4; + string ipv4 = 5; + uint32 local_admin = 6; +} + enum TUNNEL_TYPE { UNKNOWN_TUNNEL_TYPE = 0; L2TPV3_OVER_IP = 1; @@ -136,11 +158,18 @@ message EvpnMacIpAdvertisement { repeated uint32 labels = 8; } +message RTNlri { + uint32 asn = 1; + ExtendedCommunity target = 2; + uint32 length = 3; +} + message Nlri { AddressFamily af = 1; string prefix = 2; - EVPNNlri evpn_nlri = 3; - string nexthop = 4; + string nexthop = 3; + EVPNNlri evpn_nlri = 4; + RTNlri rt_nlri = 5; } enum ENCAP_SUBTLV_TYPE { @@ -196,7 +225,7 @@ message PathAttr { repeated uint32 communites = 9; string originator = 10; repeated string cluster = 11; - Nlri nlri = 12; + repeated Nlri nlri = 12; repeated TunnelEncapTLV tunnel_encap = 13; } diff --git a/api/util.go b/api/util.go index 00a4366c..591c1c59 100644 --- a/api/util.go +++ b/api/util.go @@ -19,6 +19,7 @@ var AF_IPV4_UC *AddressFamily = &AddressFamily{AFI_IP, SAFI_UNICAST} var AF_IPV6_UC *AddressFamily = &AddressFamily{AFI_IP6, SAFI_UNICAST} var AF_EVPN *AddressFamily = &AddressFamily{AFI_L2VPN, SAFI_EVPN} var AF_ENCAP *AddressFamily = &AddressFamily{AFI_IP, SAFI_ENCAP} +var AF_RTC *AddressFamily = &AddressFamily{AFI_IP, SAFI_ROUTE_TARGET_CONSTRAINTS} func (lhs *AddressFamily) Equal(rhs *AddressFamily) bool { return lhs.Afi == rhs.Afi && lhs.Safi == rhs.Safi diff --git a/packet/bgp.go b/packet/bgp.go index 096444dc..8c719d8d 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -1099,13 +1099,38 @@ func (n *RouteTargetMembershipNLRI) Len() int { } func (n *RouteTargetMembershipNLRI) String() string { - return fmt.Sprintf("%d:%s/%d", n.AS, n.RouteTarget.String(), n.Len()*8) + target := "default" + if n.RouteTarget != nil { + target = n.RouteTarget.String() + } + return fmt.Sprintf("%d:%s", n.AS, target) } func (n *RouteTargetMembershipNLRI) ToApiStruct() *api.Nlri { + var target *api.ExtendedCommunity + if n.RouteTarget != nil { + target = n.RouteTarget.ToApiStruct() + } return &api.Nlri{ Af: &api.AddressFamily{api.AFI(n.AFI()), api.SAFI(n.SAFI())}, Prefix: n.String(), + RtNlri: &api.RTNlri{ + Asn: n.AS, + Target: target, + Length: uint32(n.Length), + }, + } +} + +func NewRouteTargetMembershipNLRI(as uint32, target ExtendedCommunityInterface) *RouteTargetMembershipNLRI { + l := 12 * 8 + if as == 0 && target == nil { + l = 1 + } + return &RouteTargetMembershipNLRI{ + Length: uint8(l), + AS: as, + RouteTarget: target, } } @@ -1612,6 +1637,8 @@ func GetRouteFamily(name string) (RouteFamily, error) { return RF_VPLS, nil case "l2vpn-evpn": return RF_EVPN, nil + case "rtc": + return RF_RTC_UC, nil case "encap": return RF_ENCAP, nil } @@ -2656,9 +2683,14 @@ func (p *PathAttributeMpReachNLRI) Serialize() ([]byte, error) { } func (p *PathAttributeMpReachNLRI) ToApiStruct() *api.PathAttr { + nlri := make([]*api.Nlri, 0, len(p.Value)) + for _, v := range p.Value { + nlri = append(nlri, v.ToApiStruct()) + } return &api.PathAttr{ Type: api.BGP_ATTR_TYPE_MP_REACH_NLRI, Nexthop: p.Nexthop.String(), + Nlri: nlri, } } @@ -2778,10 +2810,11 @@ func NewPathAttributeMpUnreachNLRI(nlri []AddrPrefixInterface) *PathAttributeMpU type ExtendedCommunityInterface interface { Serialize() ([]byte, error) String() string + ToApiStruct() *api.ExtendedCommunity } type TwoOctetAsSpecificExtended struct { - SubType uint8 + SubType ExtendedCommunityAttrSubType AS uint16 LocalAdmin uint32 IsTransitive bool @@ -2794,7 +2827,7 @@ func (e *TwoOctetAsSpecificExtended) Serialize() ([]byte, error) { } else { buf[0] = byte(EC_TYPE_NON_TRANSITIVE_TWO_OCTET_AS_SPECIFIC) } - buf[1] = e.SubType + buf[1] = byte(e.SubType) binary.BigEndian.PutUint16(buf[2:], e.AS) binary.BigEndian.PutUint32(buf[4:], e.LocalAdmin) return buf, nil @@ -2804,8 +2837,18 @@ func (e *TwoOctetAsSpecificExtended) String() string { return fmt.Sprintf("%d:%d", e.AS, e.LocalAdmin) } +func (e *TwoOctetAsSpecificExtended) ToApiStruct() *api.ExtendedCommunity { + return &api.ExtendedCommunity{ + Type: api.EXTENDED_COMMUNITIE_TYPE_TWO_OCTET_AS_SPECIFIC, + Subtype: api.EXTENDED_COMMUNITIE_SUBTYPE(e.SubType), + IsTransitive: e.IsTransitive, + Asn: uint32(e.AS), + LocalAdmin: e.LocalAdmin, + } +} + type IPv4AddressSpecificExtended struct { - SubType uint8 + SubType ExtendedCommunityAttrSubType IPv4 net.IP LocalAdmin uint16 IsTransitive bool @@ -2818,7 +2861,7 @@ func (e *IPv4AddressSpecificExtended) Serialize() ([]byte, error) { } else { buf[0] = byte(EC_TYPE_NON_TRANSITIVE_IP4_SPECIFIC) } - buf[1] = e.SubType + buf[1] = byte(e.SubType) copy(buf[2:6], e.IPv4) binary.BigEndian.PutUint16(buf[6:], e.LocalAdmin) return buf, nil @@ -2828,8 +2871,18 @@ func (e *IPv4AddressSpecificExtended) String() string { return fmt.Sprintf("%s:%d", e.IPv4.String(), e.LocalAdmin) } +func (e *IPv4AddressSpecificExtended) ToApiStruct() *api.ExtendedCommunity { + return &api.ExtendedCommunity{ + Type: api.EXTENDED_COMMUNITIE_TYPE_IP4_SPECIFIC, + Subtype: api.EXTENDED_COMMUNITIE_SUBTYPE(e.SubType), + IsTransitive: e.IsTransitive, + Ipv4: e.IPv4.String(), + LocalAdmin: uint32(e.LocalAdmin), + } +} + type FourOctetAsSpecificExtended struct { - SubType uint8 + SubType ExtendedCommunityAttrSubType AS uint32 LocalAdmin uint16 IsTransitive bool @@ -2842,7 +2895,7 @@ func (e *FourOctetAsSpecificExtended) Serialize() ([]byte, error) { } else { buf[0] = byte(EC_TYPE_NON_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC) } - buf[1] = e.SubType + buf[1] = byte(e.SubType) binary.BigEndian.PutUint32(buf[2:], e.AS) binary.BigEndian.PutUint16(buf[6:], e.LocalAdmin) return buf, nil @@ -2856,6 +2909,16 @@ func (e *FourOctetAsSpecificExtended) String() string { return fmt.Sprintf("%d.%d:%d", asUpper, asLower, e.LocalAdmin) } +func (e *FourOctetAsSpecificExtended) ToApiStruct() *api.ExtendedCommunity { + return &api.ExtendedCommunity{ + Type: api.EXTENDED_COMMUNITIE_TYPE_FOUR_OCTET_AS_SPECIFIC, + Subtype: api.EXTENDED_COMMUNITIE_SUBTYPE(e.SubType), + IsTransitive: e.IsTransitive, + Asn: e.AS, + LocalAdmin: uint32(e.LocalAdmin), + } +} + type OpaqueExtendedValueInterface interface { Serialize() ([]byte, error) String() string @@ -2974,6 +3037,12 @@ func (e *OpaqueExtended) String() string { return e.Value.String() } +func (e *OpaqueExtended) ToApiStruct() *api.ExtendedCommunity { + return &api.ExtendedCommunity{ + Type: api.EXTENDED_COMMUNITIE_TYPE_OPAQUE, + } +} + func NewOpaqueExtended(isTransitive bool) *OpaqueExtended { return &OpaqueExtended{ IsTransitive: isTransitive, @@ -2999,6 +3068,10 @@ func (e *UnknownExtended) String() string { return fmt.Sprintf("%d", v) } +func (e *UnknownExtended) ToApiStruct() *api.ExtendedCommunity { + return &api.ExtendedCommunity{} +} + type PathAttributeExtendedCommunities struct { PathAttribute Value []ExtendedCommunityInterface @@ -3014,7 +3087,7 @@ func parseExtended(data []byte) (ExtendedCommunityInterface, error) { case EC_TYPE_NON_TRANSITIVE_TWO_OCTET_AS_SPECIFIC: e := &TwoOctetAsSpecificExtended{} e.IsTransitive = transitive - e.SubType = data[1] + e.SubType = ExtendedCommunityAttrSubType(data[1]) e.AS = binary.BigEndian.Uint16(data[2:4]) e.LocalAdmin = binary.BigEndian.Uint32(data[4:8]) return e, nil @@ -3024,7 +3097,7 @@ func parseExtended(data []byte) (ExtendedCommunityInterface, error) { case EC_TYPE_NON_TRANSITIVE_IP4_SPECIFIC: e := &IPv4AddressSpecificExtended{} e.IsTransitive = transitive - e.SubType = data[1] + e.SubType = ExtendedCommunityAttrSubType(data[1]) e.IPv4 = data[2:6] e.LocalAdmin = binary.BigEndian.Uint16(data[6:8]) return e, nil @@ -3034,7 +3107,7 @@ func parseExtended(data []byte) (ExtendedCommunityInterface, error) { case EC_TYPE_NON_TRANSITIVE_FOUR_OCTET_AS_SPECIFIC: e := &FourOctetAsSpecificExtended{} e.IsTransitive = transitive - e.SubType = data[1] + e.SubType = ExtendedCommunityAttrSubType(data[1]) e.AS = binary.BigEndian.Uint32(data[2:6]) e.LocalAdmin = binary.BigEndian.Uint16(data[6:8]) return e, nil |