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  }