Skip to content

Commit

Permalink
Updating support of L2VPN VPLS address family (AFI 25, SAFI 65)
Browse files Browse the repository at this point in the history
  • Loading branch information
MeneTelk0 committed Apr 24, 2023
1 parent 88da915 commit 7109696
Show file tree
Hide file tree
Showing 11 changed files with 1,810 additions and 1,486 deletions.
3,089 changes: 1,637 additions & 1,452 deletions api/attribute.pb.go

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions api/attribute.proto
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,21 @@ message EthernetSegmentIdentifier {
bytes value = 2;
}

// VPLSNLRI represents the NLRI for:
// - AFI=25, SAFI=65
message VPLSNLRI {
// One of:
// - RouteDistinguisherTwoOctetASN
// - RouteDistinguisherIPAddress
// - RouteDistinguisherFourOctetASN
google.protobuf.Any rd = 1;
uint32 ve_id = 2;
uint32 ve_block_offset = 3;
uint32 ve_block_size = 4;
uint32 label_block_base = 5;
}


// EVPNEthernetAutoDiscoveryRoute represents the NLRI for:
// - AFI=25, SAFI=70, RouteType=1
message EVPNEthernetAutoDiscoveryRoute {
Expand Down Expand Up @@ -530,6 +545,11 @@ message MUPExtended {
uint32 segment_id4 = 3;
}

message VPLSExtended {
uint32 control_flags = 1;
uint32 mtu = 2;
}

message UnknownExtended {
uint32 type = 1;
bytes value = 2;
Expand All @@ -551,6 +571,7 @@ message ExtendedCommunitiesAttribute {
// - RedirectFourOctetAsSpecificExtended
// - TrafficRemarkExtended
// - MUPExtended
// - VPLSExtended
// - UnknownExtended
repeated google.protobuf.Any communities = 1;
}
Expand Down
2 changes: 1 addition & 1 deletion api/gobgp.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions api/gobgp.proto
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ message Path {
// - IPAddressPrefix
// - LabeledIPAddressPrefix
// - EncapsulationNLRI
// - VPLSNLRI
// - EVPNEthernetAutoDiscoveryRoute
// - EVPNMACIPAdvertisementRoute
// - EVPNInclusiveMulticastEthernetTagRoute
Expand Down
6 changes: 6 additions & 0 deletions cmd/gobgp/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,10 @@ var (
Afi: api.Family_AFI_L2VPN,
Safi: api.Family_SAFI_EVPN,
}
l2vpnVPLS = &api.Family{
Afi: api.Family_AFI_L2VPN,
Safi: api.Family_SAFI_VPLS,
}
ipv4Encap = &api.Family{
Afi: api.Family_AFI_IP,
Safi: api.Family_SAFI_ENCAPSULATION,
Expand Down Expand Up @@ -437,6 +441,8 @@ func checkAddressFamily(def *api.Family) (*api.Family, error) {
f = ipv6MPLS
case "evpn":
f = evpn
case "l2vpn-vpls":
f = l2vpnVPLS
case "encap", "ipv4-encap":
f = ipv4Encap
case "ipv6-encap":
Expand Down
3 changes: 3 additions & 0 deletions docs/sources/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@
[[neighbors.afi-safis]]
[neighbors.afi-safis.config]
afi-safi-name = "l2vpn-evpn"
[[neighbors.afi-safis]]
[neighbors.afi-safis.config]
afi-safi-name = "l2vpn-vpls"
[[neighbors.afi-safis]]
[neighbors.afi-safis.config]
afi-safi-name = "rtc"
Expand Down
32 changes: 32 additions & 0 deletions pkg/apiutil/attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,18 @@ func MarshalNLRI(value bgp.AddrPrefixInterface) (*apb.Any, error) {
nlri = &api.EncapsulationNLRI{
Address: v.String(),
}
case *bgp.VPLSNLRI:
rd, err := MarshalRD(v.RD())
if err != nil {
return nil, err
}
nlri = &api.VPLSNLRI{
Rd: rd,
VeId: uint32(v.VEID),
VeBlockOffset: uint32(v.VEBlockOffset),
VeBlockSize: uint32(v.VEBlockSize),
LabelBlockBase: v.LabelBlockBase,
}
case *bgp.EVPNNLRI:
switch r := v.RouteTypeData.(type) {
case *bgp.EVPNEthernetAutoDiscoveryRoute:
Expand Down Expand Up @@ -1409,6 +1421,19 @@ func UnmarshalNLRI(rf bgp.RouteFamily, an *apb.Any) (bgp.AddrPrefixInterface, er
case bgp.RF_IPv6_ENCAP:
nlri = bgp.NewEncapv6NLRI(v.Address)
}
case *api.VPLSNLRI:
if rf == bgp.RF_VPLS {
rd, err := UnmarshalRD(v.Rd)
if err != nil {
return nil, err
}
nlri = bgp.NewVPLSNLRI(
rd,
uint16(v.VeId),
uint16(v.VeBlockOffset),
uint16(v.VeBlockSize),
v.LabelBlockBase)
}
case *api.EVPNEthernetAutoDiscoveryRoute:
if rf == bgp.RF_EVPN {
rd, err := UnmarshalRD(v.Rd)
Expand Down Expand Up @@ -1919,6 +1944,11 @@ func NewExtendedCommunitiesAttributeFromNative(a *bgp.PathAttributeExtendedCommu
SegmentId2: uint32(v.SegmentID2),
SegmentId4: v.SegmentID4,
}
case *bgp.VPLSExtended:
community = &api.VPLSExtended{
ControlFlags: uint32(v.ControlFlags),
Mtu: uint32(v.MTU),
}
case *bgp.UnknownExtended:
community = &api.UnknownExtended{
Type: uint32(v.Type),
Expand Down Expand Up @@ -1984,6 +2014,8 @@ func unmarshalExComm(a *api.ExtendedCommunitiesAttribute) (*bgp.PathAttributeExt
community = bgp.NewTrafficRemarkExtended(uint8(v.Dscp))
case *api.MUPExtended:
community = bgp.NewMUPExtended(uint16(v.SegmentId2), v.SegmentId4)
case *api.VPLSExtended:
community = bgp.NewVPLSExtended(uint8(v.ControlFlags), uint16(v.Mtu))
case *api.UnknownExtended:
community = bgp.NewUnknownExtended(bgp.ExtendedCommunityAttrType(v.Type), v.Value)
}
Expand Down
53 changes: 52 additions & 1 deletion pkg/apiutil/attribute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,51 @@ func Test_MpReachNLRIAttribute_IPv6_ENCAP(t *testing.T) {
}
}

func Test_MpReachNLRIAttribute_VPLS(t *testing.T) {
assert := assert.New(t)

nlris := make([]*apb.Any, 0, 1)
rd, err := apb.New(&api.RouteDistinguisherTwoOctetASN{
Admin: 65000,
Assigned: 100,
})
assert.Nil(err)
a, err := apb.New(&api.VPLSNLRI{
Rd: rd,
VeId: 101,
VeBlockOffset: 100,
VeBlockSize: 10,
LabelBlockBase: 1000,
})
assert.Nil(err)
nlris = append(nlris, a)

input := &api.MpReachNLRIAttribute{
Family: &api.Family{
Afi: api.Family_AFI_L2VPN,
Safi: api.Family_SAFI_VPLS,
},
NextHops: []string{"192.168.1.1"},
Nlris: nlris,
}

a, err = apb.New(input)
assert.Nil(err)
n, err := UnmarshalAttribute(a)
assert.Nil(err)

output, _ := NewMpReachNLRIAttributeFromNative(n.(*bgp.PathAttributeMpReachNLRI))
assert.Equal(input.Family.Afi, output.Family.Afi)
assert.Equal(input.Family.Safi, output.Family.Safi)
assert.Equal(input.NextHops, output.NextHops)
assert.Equal(1, len(output.Nlris))
for idx, inputNLRI := range input.Nlris {
outputNLRI := output.Nlris[idx]
assert.Equal(inputNLRI.TypeUrl, outputNLRI.TypeUrl)
assert.Equal(inputNLRI.Value, outputNLRI.Value)
}
}

func Test_MpReachNLRIAttribute_EVPN_AD_Route(t *testing.T) {
assert := assert.New(t)

Expand Down Expand Up @@ -1507,6 +1552,12 @@ func Test_ExtendedCommunitiesAttribute(t *testing.T) {
})
assert.Nil(err)
communities = append(communities, a)
a, err = apb.New(&api.VPLSExtended{
ControlFlags: 0x00,
Mtu: 1500,
})
assert.Nil(err)
communities = append(communities, a)

input := &api.ExtendedCommunitiesAttribute{
Communities: communities,
Expand All @@ -1518,7 +1569,7 @@ func Test_ExtendedCommunitiesAttribute(t *testing.T) {
assert.Nil(err)

output, _ := NewExtendedCommunitiesAttributeFromNative(n.(*bgp.PathAttributeExtendedCommunities))
assert.Equal(21, len(output.Communities))
assert.Equal(22, len(output.Communities))
for idx, inputCommunity := range input.Communities {
outputCommunity := output.Communities[idx]
assert.Equal(inputCommunity.TypeUrl, outputCommunity.TypeUrl)
Expand Down
3 changes: 3 additions & 0 deletions pkg/packet/bgp/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ func NewTestBGPUpdateMessage() *BGPMessage {
NewEVPNIPPrefixRoute(NewRouteDistinguisherFourOctetAS(5, 6), EthernetSegmentIdentifier{ESI_ARBITRARY, make([]byte, 9)}, 5, 24, "192.2.1.0", "192.3.1.1", 5),
}

prefixes6 := []AddrPrefixInterface{NewVPLSNLRI(NewRouteDistinguisherFourOctetAS(5, 6), 101, 100, 10, 1000)}

p := []PathAttributeInterface{
NewPathAttributeOrigin(3),
NewPathAttributeAsPath(aspath1),
Expand All @@ -116,6 +118,7 @@ func NewTestBGPUpdateMessage() *BGPMessage {
NewPathAttributeMpReachNLRI("fe80::", prefixes3),
NewPathAttributeMpReachNLRI("129.1.1.1", prefixes4),
NewPathAttributeMpReachNLRI("129.1.1.1", prefixes5),
NewPathAttributeMpReachNLRI("135.1.1.1", prefixes6),
NewPathAttributeMpUnreachNLRI(prefixes1),
//NewPathAttributeMpReachNLRI("112.22.2.0", []AddrPrefixInterface{}),
//NewPathAttributeMpUnreachNLRI([]AddrPrefixInterface{}),
Expand Down
82 changes: 52 additions & 30 deletions pkg/packet/bgp/vpls.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,50 @@ import (
// [RFC 4761, section 3.2.2]: https://www.rfc-editor.org/rfc/rfc4761.html#section-3.2.2.
type VPLSNLRI struct {
PrefixDefault
VEID uint16
VEBlockOffset uint16
VEBlockSize uint16
LabelBase MPLSLabelStack
VEID uint16
VEBlockOffset uint16
VEBlockSize uint16
LabelBlockBase uint32

rd RouteDistinguisherInterface
}

func (n *VPLSNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error {
if len(data) < 19 {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all VPLS NLRI bytes available")
}
/*
RFC6074 Section 7 BGP-AD and VPLS-BGP Interoperability
Both BGP-AD and VPLS-BGP [RFC4761] use the same AFI/SAFI. In order
for both BGP-AD and VPLS-BGP to co-exist, the NLRI length must be
used as a demultiplexer.
The BGP-AD NLRI has an NLRI length of 12 bytes, containing only an
8-byte RD and a 4-byte VSI-ID. VPLS-BGP [RFC4761] uses a 17-byte
NLRI length. Therefore, implementations of BGP-AD must ignore NLRI
that are greater than 12 bytes.
*/
length := int(binary.BigEndian.Uint16(data[0:2]))
if len(data) < length+2 {
return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all VPLS NLRI bytes available")
}
if length == 12 { // BGP-AD
// BGP-AD is not supported yet
return nil
}
// VPLS-BGP
n.rd = GetRouteDistinguisher(data[2:10])
n.VEID = binary.BigEndian.Uint16(data[10:12])
n.VEBlockOffset = binary.BigEndian.Uint16(data[12:14])
n.VEBlockSize = binary.BigEndian.Uint16(data[14:16])
return n.LabelBase.DecodeFromBytes(data[16:19], options...)

labelBlockBase := uint32(data[16])<<16 | uint32(data[17])<<8 | uint32(data[18])
n.LabelBlockBase = labelBlockBase >> 4

return nil
}

func (n *VPLSNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) {
buf := make([]byte, 16)
labelBaseBuf := make([]byte, 3)

binary.BigEndian.PutUint16(buf[0:2], 17)
rdbuf, err := n.rd.Serialize()
if err != nil {
Expand All @@ -62,11 +81,12 @@ func (n *VPLSNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) {
binary.BigEndian.PutUint16(buf[10:12], n.VEID)
binary.BigEndian.PutUint16(buf[12:14], n.VEBlockOffset)
binary.BigEndian.PutUint16(buf[14:16], n.VEBlockSize)
tbuf, err := n.LabelBase.Serialize(options...)
if err != nil {
return nil, err
}
return append(buf, tbuf...), nil

labelBlockBase := n.LabelBlockBase << 4
labelBaseBuf[0] = byte((labelBlockBase >> 16) & 0xff)
labelBaseBuf[1] = byte((labelBlockBase >> 8) & 0xff)
labelBaseBuf[2] = byte(labelBlockBase & 0xff)
return append(buf, labelBaseBuf...), nil
}

func (n *VPLSNLRI) AFI() uint16 {
Expand All @@ -78,26 +98,28 @@ func (n *VPLSNLRI) SAFI() uint8 {
}

func (n *VPLSNLRI) Len(options ...*MarshallingOption) int {
// Length (2) + Route Distinguisher (8) + VE ID (2) + VE Block Offset (2)
// + VE Block Size (2) + Label Block Base (3)
return 19
}

func (n *VPLSNLRI) String() string {
return fmt.Sprintf("%s:%d:%d (Block Size: %d, Label Base: %d)", n.rd, n.VEID, n.VEBlockOffset, n.VEBlockSize, n.LabelBase)
return fmt.Sprintf("%s:%d:%d (Block Size: %d, Label Block Base: %d)", n.rd, n.VEID, n.VEBlockOffset, n.VEBlockSize, n.LabelBlockBase)
}

func (n *VPLSNLRI) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
RD RouteDistinguisherInterface `json:"rd"`
VEID uint16 `json:"id"`
VEBlockOffset uint16 `json:"blockoffset"`
VEBlockSize uint16 `json:"blocksize"`
LabelBase MPLSLabelStack `json:"base"`
RD RouteDistinguisherInterface `json:"rd"`
VEID uint16 `json:"id"`
VEBlockOffset uint16 `json:"blockoffset"`
VEBlockSize uint16 `json:"blocksize"`
LabelBlockBase uint32 `json:"labelblockbase"`
}{
RD: n.rd,
VEID: n.VEID,
VEBlockOffset: n.VEBlockOffset,
VEBlockSize: n.VEBlockSize,
LabelBase: n.LabelBase,
RD: n.rd,
VEID: n.VEID,
VEBlockOffset: n.VEBlockOffset,
VEBlockSize: n.VEBlockSize,
LabelBlockBase: n.LabelBlockBase,
})
}

Expand All @@ -109,13 +131,13 @@ func (l *VPLSNLRI) Flat() map[string]string {
return map[string]string{}
}

func NewVPLSNLRI(rd RouteDistinguisherInterface, id uint16, blockOffset uint16, blockSize uint16, labelBase MPLSLabelStack) *VPLSNLRI {
func NewVPLSNLRI(rd RouteDistinguisherInterface, id uint16, blockOffset uint16, blockSize uint16, labelBlockBase uint32) *VPLSNLRI {
return &VPLSNLRI{
rd: rd,
VEID: id,
VEBlockOffset: blockOffset,
VEBlockSize: blockSize,
LabelBase: labelBase,
rd: rd,
VEID: id,
VEBlockOffset: blockOffset,
VEBlockSize: blockSize,
LabelBlockBase: labelBlockBase,
}
}

Expand Down

0 comments on commit 7109696

Please sign in to comment.