diff options
-rw-r--r-- | api/gobgp.pb.go | 128 | ||||
-rw-r--r-- | api/gobgp.proto | 36 | ||||
-rw-r--r-- | packet/bgp.go | 178 | ||||
-rw-r--r-- | packet/bgp_test.go | 3 |
4 files changed, 263 insertions, 82 deletions
diff --git a/api/gobgp.pb.go b/api/gobgp.pb.go index a7e0d90d..71e3f454 100644 --- a/api/gobgp.pb.go +++ b/api/gobgp.pb.go @@ -292,55 +292,6 @@ 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 ( @@ -563,6 +514,64 @@ func (x Error_ErrorCode) String() string { return proto.EnumName(Error_ErrorCode_name, int32(x)) } +type ExtendedCommunity_Type int32 + +const ( + ExtendedCommunity_TWO_OCTET_AS_SPECIFIC ExtendedCommunity_Type = 0 + ExtendedCommunity_IP4_SPECIFIC ExtendedCommunity_Type = 1 + ExtendedCommunity_FOUR_OCTET_AS_SPECIFIC ExtendedCommunity_Type = 2 + ExtendedCommunity_OPAQUE ExtendedCommunity_Type = 3 + ExtendedCommunity_EVPN ExtendedCommunity_Type = 4 +) + +var ExtendedCommunity_Type_name = map[int32]string{ + 0: "TWO_OCTET_AS_SPECIFIC", + 1: "IP4_SPECIFIC", + 2: "FOUR_OCTET_AS_SPECIFIC", + 3: "OPAQUE", + 4: "EVPN", +} +var ExtendedCommunity_Type_value = map[string]int32{ + "TWO_OCTET_AS_SPECIFIC": 0, + "IP4_SPECIFIC": 1, + "FOUR_OCTET_AS_SPECIFIC": 2, + "OPAQUE": 3, + "EVPN": 4, +} + +func (x ExtendedCommunity_Type) String() string { + return proto.EnumName(ExtendedCommunity_Type_name, int32(x)) +} + +type ExtendedCommunity_Subtype int32 + +const ( + ExtendedCommunity_ORIGIN_VALIDATION ExtendedCommunity_Subtype = 0 + ExtendedCommunity_ROUTE_TARGET ExtendedCommunity_Subtype = 2 + ExtendedCommunity_ROUTE_ORIGIN ExtendedCommunity_Subtype = 3 + ExtendedCommunity_ESI_LABEL ExtendedCommunity_Subtype = 4 + ExtendedCommunity_MAC_MOBILITY ExtendedCommunity_Subtype = 5 +) + +var ExtendedCommunity_Subtype_name = map[int32]string{ + 0: "ORIGIN_VALIDATION", + 2: "ROUTE_TARGET", + 3: "ROUTE_ORIGIN", + 4: "ESI_LABEL", + 5: "MAC_MOBILITY", +} +var ExtendedCommunity_Subtype_value = map[string]int32{ + "ORIGIN_VALIDATION": 0, + "ROUTE_TARGET": 2, + "ROUTE_ORIGIN": 3, + "ESI_LABEL": 4, + "MAC_MOBILITY": 5, +} + +func (x ExtendedCommunity_Subtype) String() string { + return proto.EnumName(ExtendedCommunity_Subtype_name, int32(x)) +} + type Error struct { Code Error_ErrorCode `protobuf:"varint,1,opt,name=code,enum=api.Error_ErrorCode" json:"code,omitempty"` Msg string `protobuf:"bytes,2,opt,name=msg" json:"msg,omitempty"` @@ -733,12 +742,17 @@ 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"` + Type ExtendedCommunity_Type `protobuf:"varint,1,opt,name=type,enum=api.ExtendedCommunity_Type" json:"type,omitempty"` + Subtype ExtendedCommunity_Subtype `protobuf:"varint,2,opt,name=subtype,enum=api.ExtendedCommunity_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"` + IsSingleActive bool `protobuf:"varint,7,opt,name=is_single_active" json:"is_single_active,omitempty"` + Label uint32 `protobuf:"varint,8,opt,name=label" json:"label,omitempty"` + EsImport string `protobuf:"bytes,9,opt,name=es_import" json:"es_import,omitempty"` + Sequence uint32 `protobuf:"varint,10,opt,name=sequence" json:"sequence,omitempty"` + IsSticky bool `protobuf:"varint,11,opt,name=is_sticky" json:"is_sticky,omitempty"` } func (m *ExtendedCommunity) Reset() { *m = ExtendedCommunity{} } @@ -1398,14 +1412,14 @@ func init() { proto.RegisterEnum("api.ROUTE_DISTINGUISHER_TYPE", ROUTE_DISTINGUISHER_TYPE_name, ROUTE_DISTINGUISHER_TYPE_value) proto.RegisterEnum("api.BGP_CAPABILITY", BGP_CAPABILITY_name, BGP_CAPABILITY_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.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) proto.RegisterEnum("api.Error_ErrorCode", Error_ErrorCode_name, Error_ErrorCode_value) + proto.RegisterEnum("api.ExtendedCommunity_Type", ExtendedCommunity_Type_name, ExtendedCommunity_Type_value) + proto.RegisterEnum("api.ExtendedCommunity_Subtype", ExtendedCommunity_Subtype_name, ExtendedCommunity_Subtype_value) } // Client API for Grpc service diff --git a/api/gobgp.proto b/api/gobgp.proto index 84844214..fe3d31fe 100644 --- a/api/gobgp.proto +++ b/api/gobgp.proto @@ -178,26 +178,32 @@ 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; + enum Type { + TWO_OCTET_AS_SPECIFIC = 0; + IP4_SPECIFIC = 1; + FOUR_OCTET_AS_SPECIFIC = 2; + OPAQUE = 3; + EVPN = 4; + } + Type type = 1; + enum Subtype { + ORIGIN_VALIDATION = 0; + ROUTE_TARGET = 2; + ROUTE_ORIGIN = 3; + ESI_LABEL = 4; + MAC_MOBILITY = 5; + } + Subtype subtype = 2; bool is_transitive = 3; uint32 asn = 4; string ipv4 = 5; uint32 local_admin = 6; + bool is_single_active = 7; + uint32 label = 8; + string es_import = 9; + uint32 sequence = 10; + bool is_sticky = 11; } enum TUNNEL_TYPE { diff --git a/packet/bgp.go b/packet/bgp.go index 7fd4f9e6..450d0864 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -118,9 +118,9 @@ const ( EC_SUBTYPE_FLOWSPEC_REDIRECT ExtendedCommunityAttrSubType = 0x08 EC_SUBTYPE_FLOWSPEC_TRAFFIC_REMARK ExtendedCommunityAttrSubType = 0x09 - EC_SUBTYPE_MAC_MOBILITY ExtendedCommunityAttrSubType = 0x00 - EC_SUBTYPE_ESI_MPLS_LABEL ExtendedCommunityAttrSubType = 0x01 - EC_SUBTYPE_ES_IMPORT ExtendedCommunityAttrSubType = 0x02 + EC_SUBTYPE_MAC_MOBILITY ExtendedCommunityAttrSubType = 0x00 + EC_SUBTYPE_ESI_LABEL ExtendedCommunityAttrSubType = 0x01 + EC_SUBTYPE_ES_IMPORT ExtendedCommunityAttrSubType = 0x02 ) type TunnelType uint16 @@ -3106,8 +3106,8 @@ func (e *TwoOctetAsSpecificExtended) GetTypes() (ExtendedCommunityAttrType, Exte 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), + Type: api.ExtendedCommunity_TWO_OCTET_AS_SPECIFIC, + Subtype: api.ExtendedCommunity_Subtype(e.SubType), IsTransitive: e.IsTransitive, Asn: uint32(e.AS), LocalAdmin: e.LocalAdmin, @@ -3157,8 +3157,8 @@ func (e *IPv4AddressSpecificExtended) GetTypes() (ExtendedCommunityAttrType, Ext func (e *IPv4AddressSpecificExtended) ToApiStruct() *api.ExtendedCommunity { return &api.ExtendedCommunity{ - Type: api.EXTENDED_COMMUNITIE_TYPE_IP4_SPECIFIC, - Subtype: api.EXTENDED_COMMUNITIE_SUBTYPE(e.SubType), + Type: api.ExtendedCommunity_IP4_SPECIFIC, + Subtype: api.ExtendedCommunity_Subtype(e.SubType), IsTransitive: e.IsTransitive, Ipv4: e.IPv4.String(), LocalAdmin: uint32(e.LocalAdmin), @@ -3203,8 +3203,8 @@ func (e *FourOctetAsSpecificExtended) GetTypes() (ExtendedCommunityAttrType, Ext 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), + Type: api.ExtendedCommunity_FOUR_OCTET_AS_SPECIFIC, + Subtype: api.ExtendedCommunity_Subtype(e.SubType), IsTransitive: e.IsTransitive, Asn: e.AS, LocalAdmin: uint32(e.LocalAdmin), @@ -3340,7 +3340,7 @@ func (e *OpaqueExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunit func (e *OpaqueExtended) ToApiStruct() *api.ExtendedCommunity { return &api.ExtendedCommunity{ - Type: api.EXTENDED_COMMUNITIE_TYPE_OPAQUE, + Type: api.ExtendedCommunity_OPAQUE, } } @@ -3350,6 +3350,162 @@ func NewOpaqueExtended(isTransitive bool) *OpaqueExtended { } } +type ESILabelExtended struct { + Label uint32 + IsSingleActive bool +} + +func (e *ESILabelExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_EVPN) + buf[1] = byte(EC_SUBTYPE_ESI_LABEL) + if e.IsSingleActive { + buf[2] = byte(1) + } + buf[3] = 0 + buf[4] = 0 + buf[5] = byte((e.Label >> 16) & 0xff) + buf[6] = byte((e.Label >> 8) & 0xff) + buf[7] = byte(e.Label & 0xff) + return buf, nil +} + +func (e *ESILabelExtended) String() string { + return fmt.Sprintf("ESI LABEL: Label [%d] IsSingleActive [%t]", e.Label, e.IsSingleActive) +} + +func (e *ESILabelExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_EVPN, EC_SUBTYPE_ESI_LABEL +} + +func (e *ESILabelExtended) ToApiStruct() *api.ExtendedCommunity { + return &api.ExtendedCommunity{ + Type: api.ExtendedCommunity_EVPN, + Subtype: api.ExtendedCommunity_ESI_LABEL, + IsSingleActive: e.IsSingleActive, + Label: e.Label, + } +} + +func NewESILabelExtended(label uint32, isSingleActive bool) *ESILabelExtended { + return &ESILabelExtended{ + Label: label, + IsSingleActive: isSingleActive, + } +} + +type ESImportRouteTarget struct { + ESImport net.HardwareAddr +} + +func (e *ESImportRouteTarget) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_EVPN) + buf[1] = byte(EC_SUBTYPE_ES_IMPORT) + copy(buf[2:], e.ESImport) + return buf, nil +} + +func (e *ESImportRouteTarget) String() string { + return fmt.Sprintf("ES-IMPORT ROUTE TARGET: ES-Import [%s]", e.ESImport.String()) +} + +func (e *ESImportRouteTarget) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_EVPN, EC_SUBTYPE_ES_IMPORT +} + +func (e *ESImportRouteTarget) ToApiStruct() *api.ExtendedCommunity { + return &api.ExtendedCommunity{ + Type: api.ExtendedCommunity_EVPN, + Subtype: api.ExtendedCommunity_ROUTE_TARGET, + EsImport: e.ESImport.String(), + } +} + +func NewESImportRouteTarget(mac string) *ESImportRouteTarget { + esImport, err := net.ParseMAC(mac) + if err != nil { + return nil + } + return &ESImportRouteTarget{ + ESImport: esImport, + } +} + +type MacMobilityExtended struct { + Sequence uint32 + IsSticky bool +} + +func (e *MacMobilityExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_EVPN) + buf[1] = byte(EC_SUBTYPE_MAC_MOBILITY) + if e.IsSticky { + buf[2] = byte(1) + } + binary.BigEndian.PutUint32(buf[4:], e.Sequence) + return buf, nil +} + +func (e *MacMobilityExtended) String() string { + return fmt.Sprintf("MAC MOBILITY: Seq [%d] IsSticky [%t]", e.Sequence, e.IsSticky) +} + +func (e *MacMobilityExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_EVPN, EC_SUBTYPE_MAC_MOBILITY +} + +func (e *MacMobilityExtended) ToApiStruct() *api.ExtendedCommunity { + return &api.ExtendedCommunity{ + Type: api.ExtendedCommunity_EVPN, + Subtype: api.ExtendedCommunity_MAC_MOBILITY, + Sequence: e.Sequence, + IsSticky: e.IsSticky, + } +} + +func NewMacMobilityExtended(seq uint32, isSticky bool) *MacMobilityExtended { + return &MacMobilityExtended{ + Sequence: seq, + IsSticky: isSticky, + } +} + +func parseEvpnExtended(data []byte) (ExtendedCommunityInterface, error) { + if ExtendedCommunityAttrType(data[0]) != EC_TYPE_EVPN { + return nil, fmt.Errorf("ext comm type is not EC_TYPE_EVPN: %d", data[0]) + } + subType := ExtendedCommunityAttrSubType(data[1]) + switch subType { + case EC_SUBTYPE_ESI_LABEL: + var isSingleActive bool + if data[2] > 0 { + isSingleActive = true + } + label := uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7]) + return &ESILabelExtended{ + IsSingleActive: isSingleActive, + Label: label, + }, nil + case EC_SUBTYPE_ES_IMPORT: + return &ESImportRouteTarget{ + ESImport: net.HardwareAddr(data[2:8]), + }, nil + case EC_SUBTYPE_MAC_MOBILITY: + var isSticky bool + if data[2] > 0 { + isSticky = true + } + seq := binary.BigEndian.Uint32(data[4:8]) + return &MacMobilityExtended{ + Sequence: seq, + IsSticky: isSticky, + }, nil + } + return nil, fmt.Errorf("unknown subtype: %d", subType) +} + type UnknownExtended struct { Type BGPAttrType Value []byte @@ -3424,6 +3580,8 @@ func parseExtended(data []byte) (ExtendedCommunityInterface, error) { e := NewOpaqueExtended(transitive) err := e.DecodeFromBytes(data[1:8]) return e, err + case EC_TYPE_EVPN: + return parseEvpnExtended(data) default: e := &UnknownExtended{} e.Type = BGPAttrType(data[0]) diff --git a/packet/bgp_test.go b/packet/bgp_test.go index 983914f1..528b3c4c 100644 --- a/packet/bgp_test.go +++ b/packet/bgp_test.go @@ -67,6 +67,9 @@ func update() *BGPMessage { Value: &DefaultOpaqueExtendedValue{[]byte{0, 1, 2, 3, 4, 5, 6, 7}}, }, &UnknownExtended{Type: 99, Value: []byte{0, 1, 2, 3, 4, 5, 6, 7}}, + NewESILabelExtended(1000, true), + NewESImportRouteTarget("11:22:33:44:55:66"), + NewMacMobilityExtended(123, false), } mp_nlri := []AddrPrefixInterface{ |