summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--api/gobgp.pb.go105
-rw-r--r--api/gobgp.proto37
-rw-r--r--api/util.go1
-rw-r--r--packet/bgp.go93
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