diff --git a/pkg/packet/bgp/bgp.go b/pkg/packet/bgp/bgp.go index a5e2fc932..fad11c1f4 100644 --- a/pkg/packet/bgp/bgp.go +++ b/pkg/packet/bgp/bgp.go @@ -189,10 +189,11 @@ const ( EC_SUBTYPE_L2_INFO ExtendedCommunityAttrSubType = 0x0A // EC_TYPE: 0x80 EC_SUBTYPE_FLOWSPEC_REDIRECT_IP6 ExtendedCommunityAttrSubType = 0x0B // EC_TYPE: 0x80 - EC_SUBTYPE_MAC_MOBILITY ExtendedCommunityAttrSubType = 0x00 // EC_TYPE: 0x06 - EC_SUBTYPE_ESI_LABEL ExtendedCommunityAttrSubType = 0x01 // EC_TYPE: 0x06 - EC_SUBTYPE_ES_IMPORT ExtendedCommunityAttrSubType = 0x02 // EC_TYPE: 0x06 - EC_SUBTYPE_ROUTER_MAC ExtendedCommunityAttrSubType = 0x03 // EC_TYPE: 0x06 + EC_SUBTYPE_MAC_MOBILITY ExtendedCommunityAttrSubType = 0x00 // EC_TYPE: 0x06 + EC_SUBTYPE_ESI_LABEL ExtendedCommunityAttrSubType = 0x01 // EC_TYPE: 0x06 + EC_SUBTYPE_ES_IMPORT ExtendedCommunityAttrSubType = 0x02 // EC_TYPE: 0x06 + EC_SUBTYPE_ROUTER_MAC ExtendedCommunityAttrSubType = 0x03 // EC_TYPE: 0x06 + EC_SUBTYPE_L2_ATTRIBUTES ExtendedCommunityAttrSubType = 0x04 // EC_TYPE: 0x06 EC_SUBTYPE_UUID_BASED_RT ExtendedCommunityAttrSubType = 0x11 ) @@ -3142,7 +3143,7 @@ func (er *EVPNIPPrefixRoute) DecodeFromBytes(data []byte) error { if er.Label, err = labelDecode(data[offset : offset+3]); err != nil { return err } - //offset += 3 + // offset += 3 return nil } @@ -9876,7 +9877,7 @@ const ( BGP_ERROR_SUB_OTHER_CONFIGURATION_CHANGE BGP_ERROR_SUB_CONNECTION_COLLISION_RESOLUTION BGP_ERROR_SUB_OUT_OF_RESOURCES - BGP_ERROR_SUB_HARD_RESET //draft-ietf-idr-bgp-gr-notification-07 + BGP_ERROR_SUB_HARD_RESET // draft-ietf-idr-bgp-gr-notification-07 ) // Constants for BGP_ERROR_SUB_ADMINISTRATIVE_SHUTDOWN and BGP_ERROR_SUB_ADMINISTRATIVE_RESET @@ -12254,6 +12255,98 @@ func NewRoutersMacExtended(mac string) *RouterMacExtended { } } +type Layer2AttributesExtended struct { + HasCILabel bool + HasFlowLabel bool + HasControlWord bool + IsPrimaryPe bool + IsBackupPe bool + Mtu uint16 +} + +type EvpnControlFlag uint8 + +const ( + BACKUP_PE EvpnControlFlag = 1 << 0 + PRIMARY_PE EvpnControlFlag = 1 << 1 + CONTROL_WORD EvpnControlFlag = 1 << 2 + FLOW_LABEL EvpnControlFlag = 1 << 3 + CI_LABEL EvpnControlFlag = 1 << 4 +) + +func (e *Layer2AttributesExtended) Serialize() ([]byte, error) { + buf := make([]byte, 8) + buf[0] = byte(EC_TYPE_EVPN) + buf[1] = byte(EC_SUBTYPE_L2_ATTRIBUTES) + + if e.IsBackupPe { + buf[3] |= uint8(BACKUP_PE) + } else if e.IsPrimaryPe { + buf[3] |= uint8(PRIMARY_PE) + } + if e.HasControlWord { + buf[3] |= uint8(CONTROL_WORD) + } + if e.HasFlowLabel { + buf[3] |= uint8(FLOW_LABEL) + } + if e.HasCILabel { + buf[3] |= uint8(CI_LABEL) + } + binary.BigEndian.PutUint16(buf[4:6], e.Mtu) + return buf, nil +} + +func (e *Layer2AttributesExtended) String() string { + buf := bytes.NewBuffer(make([]byte, 0, 32)) + buf.WriteString("evpn-l2-info: ") + if e.IsPrimaryPe { + buf.WriteString("is-primary-pe, ") + } + if e.IsBackupPe { + buf.WriteString("is-backup-pe, ") + } + if e.HasControlWord { + buf.WriteString("control-word, ") + } + if e.HasFlowLabel { + buf.WriteString("flow-label, ") + } + if e.HasCILabel { + buf.WriteString("ci-label, ") + } + + buf.WriteString("mtu " + strconv.FormatUint(uint64(e.Mtu), 10)) + return buf.String() +} + +func (e *Layer2AttributesExtended) MarshalJSON() ([]byte, error) { + t, s := e.GetTypes() + return json.Marshal(struct { + Type ExtendedCommunityAttrType `json:"type"` + Subtype ExtendedCommunityAttrSubType `json:"subtype"` + CILabel bool `json:"ci_label,omitempty"` + FlowLabel bool `json:"flow_label,omitempty"` + ControlWord bool `json:"control_word,omitempty"` + PrimaryPe bool `json:"is_primary_pe,omitempty"` + BackupPe bool `json:"is_backup_pe,omitempty"` + Mtu uint16 `json:"mtu"` + }{ + Type: t, + Subtype: s, + CILabel: e.HasCILabel, + FlowLabel: e.HasFlowLabel, + ControlWord: e.HasControlWord, + PrimaryPe: e.IsPrimaryPe, + BackupPe: e.IsBackupPe, + Mtu: e.Mtu, + }) +} + +func (e *Layer2AttributesExtended) GetTypes() (ExtendedCommunityAttrType, ExtendedCommunityAttrSubType) { + return EC_TYPE_EVPN, EC_SUBTYPE_L2_ATTRIBUTES +} + func parseEvpnExtended(data []byte) (ExtendedCommunityInterface, error) { if ExtendedCommunityAttrType(data[0]) != EC_TYPE_EVPN { return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("ext comm type is not EC_TYPE_EVPN: %d", data[0])) @@ -12288,6 +12381,21 @@ func parseEvpnExtended(data []byte) (ExtendedCommunityInterface, error) { return &RouterMacExtended{ Mac: net.HardwareAddr(data[2:8]), }, nil + case EC_SUBTYPE_L2_ATTRIBUTES: + if flags := data[3]; flags == 0 { + return &Layer2AttributesExtended{ + Mtu: binary.BigEndian.Uint16(data[4:6]), + }, nil + } else { + return &Layer2AttributesExtended{ + HasCILabel: flags&uint8(CI_LABEL) > 0, + HasFlowLabel: flags&uint8(FLOW_LABEL) > 0, + HasControlWord: flags&uint8(CONTROL_WORD) > 0, + IsPrimaryPe: flags&uint8(PRIMARY_PE) > 0, + IsBackupPe: flags&uint8(BACKUP_PE) > 0, + Mtu: binary.BigEndian.Uint16(data[4:6]), + }, nil + } } return nil, NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, fmt.Sprintf("unknown evpn subtype: %d", subType)) } @@ -14855,6 +14963,10 @@ func (e *RouterMacExtended) Flat() map[string]string { return map[string]string{} } +func (e *Layer2AttributesExtended) Flat() map[string]string { + return map[string]string{} +} + func (e *TrafficRateExtended) Flat() map[string]string { return map[string]string{} }