github.com/osrg/gobgp/v3@v3.30.0/pkg/packet/bgp/vpls.go (about) 1 package bgp 2 3 import ( 4 "encoding/binary" 5 "encoding/json" 6 "fmt" 7 ) 8 9 // VPLSNLRI represents an NLRI for VPLS, as defined in [RFC 4761, section 3.2.2]. 10 // 11 // Path Attribute - MP_REACH_NLRI 12 // Flags: 0x90, Optional, Extended-Length, Non-transitive, Complete 13 // Type Code: MP_REACH_NLRI (14) 14 // Length: 28 15 // Address family identifier (AFI): Layer-2 VPN (25) 16 // Subsequent address family identifier (SAFI): VPLS (65) 17 // Next hop: 192.0.2.7 18 // IPv4 Address: 192.0.2.7 19 // Number of Subnetwork points of attachment (SNPA): 0 20 // Network Layer Reachability Information (NLRI) 21 // Length: 17 22 // RD: 65017:104 23 // CE-ID: 1 24 // Label Block Offset: 1 25 // Label Block Size: 8 26 // Label Block Base: 800000 (bottom) 27 // 28 // [RFC 4761, section 3.2.2]: https://www.rfc-editor.org/rfc/rfc4761.html#section-3.2.2. 29 type VPLSNLRI struct { 30 PrefixDefault 31 VEID uint16 32 VEBlockOffset uint16 33 VEBlockSize uint16 34 LabelBlockBase uint32 35 36 rd RouteDistinguisherInterface 37 } 38 39 func (n *VPLSNLRI) DecodeFromBytes(data []byte, options ...*MarshallingOption) error { 40 /* 41 RFC6074 Section 7 BGP-AD and VPLS-BGP Interoperability 42 Both BGP-AD and VPLS-BGP [RFC4761] use the same AFI/SAFI. In order 43 for both BGP-AD and VPLS-BGP to co-exist, the NLRI length must be 44 used as a demultiplexer. 45 46 The BGP-AD NLRI has an NLRI length of 12 bytes, containing only an 47 8-byte RD and a 4-byte VSI-ID. VPLS-BGP [RFC4761] uses a 17-byte 48 NLRI length. Therefore, implementations of BGP-AD must ignore NLRI 49 that are greater than 12 bytes. 50 */ 51 length := int(binary.BigEndian.Uint16(data[0:2])) 52 if len(data) < length+2 { 53 return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all VPLS NLRI bytes available") 54 } 55 if length == 12 { // BGP-AD 56 // BGP-AD is not supported yet 57 return nil 58 } 59 // VPLS-BGP 60 n.rd = GetRouteDistinguisher(data[2:10]) 61 n.VEID = binary.BigEndian.Uint16(data[10:12]) 62 n.VEBlockOffset = binary.BigEndian.Uint16(data[12:14]) 63 n.VEBlockSize = binary.BigEndian.Uint16(data[14:16]) 64 65 labelBlockBase := uint32(data[16])<<16 | uint32(data[17])<<8 | uint32(data[18]) 66 n.LabelBlockBase = labelBlockBase >> 4 67 68 return nil 69 } 70 71 func (n *VPLSNLRI) Serialize(options ...*MarshallingOption) ([]byte, error) { 72 buf := make([]byte, 16) 73 labelBaseBuf := make([]byte, 3) 74 75 binary.BigEndian.PutUint16(buf[0:2], 17) 76 rdbuf, err := n.rd.Serialize() 77 if err != nil { 78 return nil, err 79 } 80 copy(buf[2:10], rdbuf[:8]) 81 binary.BigEndian.PutUint16(buf[10:12], n.VEID) 82 binary.BigEndian.PutUint16(buf[12:14], n.VEBlockOffset) 83 binary.BigEndian.PutUint16(buf[14:16], n.VEBlockSize) 84 85 labelBlockBase := n.LabelBlockBase << 4 86 labelBaseBuf[0] = byte((labelBlockBase >> 16) & 0xff) 87 labelBaseBuf[1] = byte((labelBlockBase >> 8) & 0xff) 88 labelBaseBuf[2] = byte(labelBlockBase & 0xff) 89 return append(buf, labelBaseBuf...), nil 90 } 91 92 func (n *VPLSNLRI) AFI() uint16 { 93 return AFI_L2VPN 94 } 95 96 func (n *VPLSNLRI) SAFI() uint8 { 97 return SAFI_VPLS 98 } 99 100 func (n *VPLSNLRI) Len(options ...*MarshallingOption) int { 101 // Length (2) + Route Distinguisher (8) + VE ID (2) + VE Block Offset (2) 102 // + VE Block Size (2) + Label Block Base (3) 103 return 19 104 } 105 106 func (n *VPLSNLRI) String() string { 107 return fmt.Sprintf("%s:%d:%d (Block Size: %d, Label Block Base: %d)", n.rd, n.VEID, n.VEBlockOffset, n.VEBlockSize, n.LabelBlockBase) 108 } 109 110 func (n *VPLSNLRI) MarshalJSON() ([]byte, error) { 111 return json.Marshal(struct { 112 RD RouteDistinguisherInterface `json:"rd"` 113 VEID uint16 `json:"id"` 114 VEBlockOffset uint16 `json:"blockoffset"` 115 VEBlockSize uint16 `json:"blocksize"` 116 LabelBlockBase uint32 `json:"labelblockbase"` 117 }{ 118 RD: n.rd, 119 VEID: n.VEID, 120 VEBlockOffset: n.VEBlockOffset, 121 VEBlockSize: n.VEBlockSize, 122 LabelBlockBase: n.LabelBlockBase, 123 }) 124 } 125 126 func (n *VPLSNLRI) RD() RouteDistinguisherInterface { 127 return n.rd 128 } 129 130 func (l *VPLSNLRI) Flat() map[string]string { 131 return map[string]string{} 132 } 133 134 func NewVPLSNLRI(rd RouteDistinguisherInterface, id uint16, blockOffset uint16, blockSize uint16, labelBlockBase uint32) *VPLSNLRI { 135 return &VPLSNLRI{ 136 rd: rd, 137 VEID: id, 138 VEBlockOffset: blockOffset, 139 VEBlockSize: blockSize, 140 LabelBlockBase: labelBlockBase, 141 } 142 } 143 144 // VPLSExtended repsents BGP VPLS Extended Community as described in [RFC 4761, section 3.2.4]. 145 // 146 // Path Attribute - EXTENDED_COMMUNITIES 147 // Flags: 0xc0, Optional, Transitive, Complete 148 // Type Code: EXTENDED_COMMUNITIES (16) 149 // Length: 16 150 // Carried extended communities: (2 communities) 151 // Route Target: 65017:104 [Transitive 2-Octet AS-Specific] 152 // Layer2 Info: [Generic Transitive Experimental Use] 153 // Type: Generic Transitive Experimental Use (0x80) 154 // Subtype (Experimental): Layer2 Info (0x0a) 155 // Encaps Type: VPLS (19) 156 // Control Flags: 0x00 157 // Layer-2 MTU: 0 158 // 159 // [RFC 4761, section 3.2.4]: https://www.rfc-editor.org/rfc/rfc4761.html#section-3.2.4 160 type VPLSExtended struct { 161 SubType ExtendedCommunityAttrSubType 162 ControlFlags uint8 163 MTU uint16 164 } 165 166 func (e *VPLSExtended) Serialize() ([]byte, error) { 167 buf := make([]byte, 8) 168 buf[0] = byte(EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL) 169 buf[1] = byte(EC_SUBTYPE_L2_INFO) 170 buf[2] = byte(LAYER2ENCAPSULATION_TYPE_VPLS) 171 buf[3] = byte(e.ControlFlags) 172 binary.BigEndian.PutUint16(buf[4:6], e.MTU) 173 // 6-8: reserved, but Juniper says this is "site preference" 174 return buf, nil 175 } 176 177 func (e *VPLSExtended) String() string { 178 return fmt.Sprintf("encaps: VPLS, control flags:0x%x, mtu: %d", e.ControlFlags, e.MTU) 179 } 180 181 func (e *VPLSExtended) MarshalJSON() ([]byte, error) { 182 t, s := e.GetTypes() 183 return json.Marshal(struct { 184 Type ExtendedCommunityAttrType `json:"type"` 185 Subtype ExtendedCommunityAttrSubType `json:"subtype"` 186 Value string `json:"value"` 187 }{ 188 Type: t, 189 Subtype: s, 190 Value: e.String(), 191 }) 192 } 193 194 func (e *VPLSExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { 195 return EC_TYPE_GENERIC_TRANSITIVE_EXPERIMENTAL, EC_SUBTYPE_L2_INFO 196 } 197 198 func (e *VPLSExtended) Flat() map[string]string { 199 return map[string]string{} 200 } 201 202 func NewVPLSExtended(flags uint8, mtu uint16) *VPLSExtended { 203 return &VPLSExtended{ 204 SubType: EC_SUBTYPE_L2_INFO, 205 ControlFlags: flags, 206 MTU: mtu, 207 } 208 }