diff options
Diffstat (limited to 'framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpUpdate.java')
-rw-r--r-- | framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpUpdate.java | 1707 |
1 files changed, 0 insertions, 1707 deletions
diff --git a/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpUpdate.java b/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpUpdate.java deleted file mode 100644 index babc8507..00000000 --- a/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpUpdate.java +++ /dev/null @@ -1,1707 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.onosproject.routing.bgp; - -import org.apache.commons.lang3.tuple.Pair; -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.buffer.ChannelBuffers; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.onlab.packet.Ip4Address; -import org.onlab.packet.Ip4Prefix; -import org.onlab.packet.Ip6Address; -import org.onlab.packet.Ip6Prefix; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -/** - * A class for handling BGP UPDATE messages. - */ -final class BgpUpdate { - private static final Logger log = LoggerFactory.getLogger(BgpUpdate.class); - - /** - * Default constructor. - * <p> - * The constructor is private to prevent creating an instance of - * this utility class. - */ - private BgpUpdate() { - } - - /** - * Processes BGP UPDATE message. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param message the message to process - */ - static void processBgpUpdate(BgpSession bgpSession, - ChannelHandlerContext ctx, - ChannelBuffer message) { - DecodedBgpRoutes decodedBgpRoutes = new DecodedBgpRoutes(); - - int minLength = - BgpConstants.BGP_UPDATE_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH; - if (message.readableBytes() < minLength) { - log.debug("BGP RX UPDATE Error from {}: " + - "Message length {} too short. Must be at least {}", - bgpSession.remoteInfo().address(), - message.readableBytes(), minLength); - // - // ERROR: Bad Message Length - // - // Send NOTIFICATION and close the connection - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotificationBadMessageLength( - message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - return; - } - - log.debug("BGP RX UPDATE message from {}", - bgpSession.remoteInfo().address()); - - // - // Parse the UPDATE message - // - - // - // Parse the Withdrawn Routes - // - int withdrawnRoutesLength = message.readUnsignedShort(); - if (withdrawnRoutesLength > message.readableBytes()) { - // ERROR: Malformed Attribute List - actionsBgpUpdateMalformedAttributeList(bgpSession, ctx); - return; - } - Collection<Ip4Prefix> withdrawnPrefixes = null; - try { - withdrawnPrefixes = parsePackedIp4Prefixes(withdrawnRoutesLength, - message); - } catch (BgpMessage.BgpParseException e) { - // ERROR: Invalid Network Field - log.debug("Exception parsing Withdrawn Prefixes from BGP peer {}: ", - bgpSession.remoteInfo().bgpId(), e); - actionsBgpUpdateInvalidNetworkField(bgpSession, ctx); - return; - } - for (Ip4Prefix prefix : withdrawnPrefixes) { - log.debug("BGP RX UPDATE message WITHDRAWN from {}: {}", - bgpSession.remoteInfo().address(), prefix); - BgpRouteEntry bgpRouteEntry = bgpSession.findBgpRoute(prefix); - if (bgpRouteEntry != null) { - decodedBgpRoutes.deletedUnicastRoutes4.put(prefix, - bgpRouteEntry); - } - } - - // - // Parse the Path Attributes - // - try { - parsePathAttributes(bgpSession, ctx, message, decodedBgpRoutes); - } catch (BgpMessage.BgpParseException e) { - log.debug("Exception parsing Path Attributes from BGP peer {}: ", - bgpSession.remoteInfo().bgpId(), e); - // NOTE: The session was already closed, so nothing else to do - return; - } - - // - // Update the BGP RIB-IN - // - for (Ip4Prefix ip4Prefix : - decodedBgpRoutes.deletedUnicastRoutes4.keySet()) { - bgpSession.removeBgpRoute(ip4Prefix); - } - // - for (BgpRouteEntry bgpRouteEntry : - decodedBgpRoutes.addedUnicastRoutes4.values()) { - bgpSession.addBgpRoute(bgpRouteEntry); - } - // - for (Ip6Prefix ip6Prefix : - decodedBgpRoutes.deletedUnicastRoutes6.keySet()) { - bgpSession.removeBgpRoute(ip6Prefix); - } - // - for (BgpRouteEntry bgpRouteEntry : - decodedBgpRoutes.addedUnicastRoutes6.values()) { - bgpSession.addBgpRoute(bgpRouteEntry); - } - - // - // Push the updates to the BGP Merged RIB - // - BgpRouteSelector bgpRouteSelector = - bgpSession.getBgpSessionManager().getBgpRouteSelector(); - bgpRouteSelector.routeUpdates(bgpSession, - decodedBgpRoutes.addedUnicastRoutes4.values(), - decodedBgpRoutes.deletedUnicastRoutes4.values()); - bgpRouteSelector.routeUpdates(bgpSession, - decodedBgpRoutes.addedUnicastRoutes6.values(), - decodedBgpRoutes.deletedUnicastRoutes6.values()); - - // Start the Session Timeout timer - bgpSession.restartSessionTimeoutTimer(ctx); - } - - /** - * Parse BGP Path Attributes from the BGP UPDATE message. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param message the message to parse - * @param decodedBgpRoutes the container to store the decoded BGP Route - * Entries. It might already contain some route entries such as withdrawn - * IPv4 prefixes - * @throws BgpMessage.BgpParseException - */ - // CHECKSTYLE IGNORE MethodLength FOR NEXT 300 LINES - private static void parsePathAttributes( - BgpSession bgpSession, - ChannelHandlerContext ctx, - ChannelBuffer message, - DecodedBgpRoutes decodedBgpRoutes) - throws BgpMessage.BgpParseException { - - // - // Parsed values - // - Short origin = -1; // Mandatory - BgpRouteEntry.AsPath asPath = null; // Mandatory - // Legacy NLRI (RFC 4271). Mandatory NEXT_HOP if legacy NLRI is used - MpNlri legacyNlri = new MpNlri( - BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4, - BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST); - long multiExitDisc = // Optional - BgpConstants.Update.MultiExitDisc.LOWEST_MULTI_EXIT_DISC; - Long localPref = null; // Mandatory - Long aggregatorAsNumber = null; // Optional: unused - Ip4Address aggregatorIpAddress = null; // Optional: unused - Collection<MpNlri> mpNlriReachList = new ArrayList<>(); // Optional - Collection<MpNlri> mpNlriUnreachList = new ArrayList<>(); // Optional - - // - // Get and verify the Path Attributes Length - // - int pathAttributeLength = message.readUnsignedShort(); - if (pathAttributeLength > message.readableBytes()) { - // ERROR: Malformed Attribute List - actionsBgpUpdateMalformedAttributeList(bgpSession, ctx); - String errorMsg = "Malformed Attribute List"; - throw new BgpMessage.BgpParseException(errorMsg); - } - if (pathAttributeLength == 0) { - return; - } - - // - // Parse the Path Attributes - // - int pathAttributeEnd = message.readerIndex() + pathAttributeLength; - while (message.readerIndex() < pathAttributeEnd) { - int attrFlags = message.readUnsignedByte(); - if (message.readerIndex() >= pathAttributeEnd) { - // ERROR: Malformed Attribute List - actionsBgpUpdateMalformedAttributeList(bgpSession, ctx); - String errorMsg = "Malformed Attribute List"; - throw new BgpMessage.BgpParseException(errorMsg); - } - int attrTypeCode = message.readUnsignedByte(); - - // The Attribute Flags - boolean optionalBit = ((0x80 & attrFlags) != 0); - boolean transitiveBit = ((0x40 & attrFlags) != 0); - boolean partialBit = ((0x20 & attrFlags) != 0); - boolean extendedLengthBit = ((0x10 & attrFlags) != 0); - - // The Attribute Length - int attrLen = 0; - int attrLenOctets = 1; - if (extendedLengthBit) { - attrLenOctets = 2; - } - if (message.readerIndex() + attrLenOctets > pathAttributeEnd) { - // ERROR: Malformed Attribute List - actionsBgpUpdateMalformedAttributeList(bgpSession, ctx); - String errorMsg = "Malformed Attribute List"; - throw new BgpMessage.BgpParseException(errorMsg); - } - if (extendedLengthBit) { - attrLen = message.readUnsignedShort(); - } else { - attrLen = message.readUnsignedByte(); - } - if (message.readerIndex() + attrLen > pathAttributeEnd) { - // ERROR: Malformed Attribute List - actionsBgpUpdateMalformedAttributeList(bgpSession, ctx); - String errorMsg = "Malformed Attribute List"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - // Verify the Attribute Flags - verifyBgpUpdateAttributeFlags(bgpSession, ctx, attrTypeCode, - attrLen, attrFlags, message); - - // - // Extract the Attribute Value based on the Attribute Type Code - // - switch (attrTypeCode) { - - case BgpConstants.Update.Origin.TYPE: - // Attribute Type Code ORIGIN - origin = parseAttributeTypeOrigin(bgpSession, ctx, - attrTypeCode, attrLen, - attrFlags, message); - break; - - case BgpConstants.Update.AsPath.TYPE: - // Attribute Type Code AS_PATH - asPath = parseAttributeTypeAsPath(bgpSession, ctx, - attrTypeCode, attrLen, - attrFlags, message); - break; - - case BgpConstants.Update.NextHop.TYPE: - // Attribute Type Code NEXT_HOP - legacyNlri.nextHop4 = - parseAttributeTypeNextHop(bgpSession, ctx, - attrTypeCode, attrLen, - attrFlags, message); - break; - - case BgpConstants.Update.MultiExitDisc.TYPE: - // Attribute Type Code MULTI_EXIT_DISC - multiExitDisc = - parseAttributeTypeMultiExitDisc(bgpSession, ctx, - attrTypeCode, attrLen, - attrFlags, message); - break; - - case BgpConstants.Update.LocalPref.TYPE: - // Attribute Type Code LOCAL_PREF - localPref = - parseAttributeTypeLocalPref(bgpSession, ctx, - attrTypeCode, attrLen, - attrFlags, message); - break; - - case BgpConstants.Update.AtomicAggregate.TYPE: - // Attribute Type Code ATOMIC_AGGREGATE - parseAttributeTypeAtomicAggregate(bgpSession, ctx, - attrTypeCode, attrLen, - attrFlags, message); - // Nothing to do: this attribute is primarily informational - break; - - case BgpConstants.Update.Aggregator.TYPE: - // Attribute Type Code AGGREGATOR - Pair<Long, Ip4Address> aggregator = - parseAttributeTypeAggregator(bgpSession, ctx, - attrTypeCode, attrLen, - attrFlags, message); - aggregatorAsNumber = aggregator.getLeft(); - aggregatorIpAddress = aggregator.getRight(); - break; - - case BgpConstants.Update.MpReachNlri.TYPE: - // Attribute Type Code MP_REACH_NLRI - MpNlri mpNlriReach = - parseAttributeTypeMpReachNlri(bgpSession, ctx, - attrTypeCode, - attrLen, - attrFlags, message); - if (mpNlriReach != null) { - mpNlriReachList.add(mpNlriReach); - } - break; - - case BgpConstants.Update.MpUnreachNlri.TYPE: - // Attribute Type Code MP_UNREACH_NLRI - MpNlri mpNlriUnreach = - parseAttributeTypeMpUnreachNlri(bgpSession, ctx, - attrTypeCode, attrLen, - attrFlags, message); - if (mpNlriUnreach != null) { - mpNlriUnreachList.add(mpNlriUnreach); - } - break; - - default: - // NOTE: Parse any new Attribute Types if needed - if (!optionalBit) { - // ERROR: Unrecognized Well-known Attribute - actionsBgpUpdateUnrecognizedWellKnownAttribute( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, - message); - String errorMsg = "Unrecognized Well-known Attribute: " + - attrTypeCode; - throw new BgpMessage.BgpParseException(errorMsg); - } - - // Skip the data from the unrecognized attribute - log.debug("BGP RX UPDATE message from {}: " + - "Unrecognized Attribute Type {}", - bgpSession.remoteInfo().address(), attrTypeCode); - message.skipBytes(attrLen); - break; - } - } - - // - // Parse the NLRI (Network Layer Reachability Information) - // - int nlriLength = message.readableBytes(); - try { - Collection<Ip4Prefix> addedPrefixes4 = - parsePackedIp4Prefixes(nlriLength, message); - // Store it inside the legacy NLRI wrapper - legacyNlri.nlri4 = addedPrefixes4; - } catch (BgpMessage.BgpParseException e) { - // ERROR: Invalid Network Field - log.debug("Exception parsing NLRI from BGP peer {}: ", - bgpSession.remoteInfo().bgpId(), e); - actionsBgpUpdateInvalidNetworkField(bgpSession, ctx); - // Rethrow the exception - throw e; - } - - // Verify the Well-known Attributes - verifyBgpUpdateWellKnownAttributes(bgpSession, ctx, origin, asPath, - localPref, legacyNlri, - mpNlriReachList); - - // - // Generate the deleted routes - // - for (MpNlri mpNlri : mpNlriUnreachList) { - BgpRouteEntry bgpRouteEntry; - - // The deleted IPv4 routes - for (Ip4Prefix prefix : mpNlri.nlri4) { - bgpRouteEntry = bgpSession.findBgpRoute(prefix); - if (bgpRouteEntry != null) { - decodedBgpRoutes.deletedUnicastRoutes4.put(prefix, - bgpRouteEntry); - } - } - - // The deleted IPv6 routes - for (Ip6Prefix prefix : mpNlri.nlri6) { - bgpRouteEntry = bgpSession.findBgpRoute(prefix); - if (bgpRouteEntry != null) { - decodedBgpRoutes.deletedUnicastRoutes6.put(prefix, - bgpRouteEntry); - } - } - } - - // - // Generate the added routes - // - mpNlriReachList.add(legacyNlri); - for (MpNlri mpNlri : mpNlriReachList) { - BgpRouteEntry bgpRouteEntry; - - // The added IPv4 routes - for (Ip4Prefix prefix : mpNlri.nlri4) { - bgpRouteEntry = - new BgpRouteEntry(bgpSession, prefix, mpNlri.nextHop4, - origin.byteValue(), asPath, localPref); - bgpRouteEntry.setMultiExitDisc(multiExitDisc); - if (bgpRouteEntry.hasAsPathLoop(bgpSession.localInfo().asNumber())) { - log.debug("BGP RX UPDATE message IGNORED from {}: {} " + - "nextHop {}: contains AS Path loop", - bgpSession.remoteInfo().address(), prefix, - mpNlri.nextHop4); - continue; - } else { - log.debug("BGP RX UPDATE message ADDED from {}: {} nextHop {}", - bgpSession.remoteInfo().address(), prefix, - mpNlri.nextHop4); - } - // Remove from the collection of deleted routes - decodedBgpRoutes.deletedUnicastRoutes4.remove(prefix); - decodedBgpRoutes.addedUnicastRoutes4.put(prefix, - bgpRouteEntry); - } - - // The added IPv6 routes - for (Ip6Prefix prefix : mpNlri.nlri6) { - bgpRouteEntry = - new BgpRouteEntry(bgpSession, prefix, mpNlri.nextHop6, - origin.byteValue(), asPath, localPref); - bgpRouteEntry.setMultiExitDisc(multiExitDisc); - if (bgpRouteEntry.hasAsPathLoop(bgpSession.localInfo().asNumber())) { - log.debug("BGP RX UPDATE message IGNORED from {}: {} " + - "nextHop {}: contains AS Path loop", - bgpSession.remoteInfo().address(), prefix, - mpNlri.nextHop6); - continue; - } else { - log.debug("BGP RX UPDATE message ADDED from {}: {} nextHop {}", - bgpSession.remoteInfo().address(), prefix, - mpNlri.nextHop6); - } - // Remove from the collection of deleted routes - decodedBgpRoutes.deletedUnicastRoutes6.remove(prefix); - decodedBgpRoutes.addedUnicastRoutes6.put(prefix, - bgpRouteEntry); - } - } - } - - /** - * Verifies BGP UPDATE Well-known Attributes. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param origin the ORIGIN well-known mandatory attribute - * @param asPath the AS_PATH well-known mandatory attribute - * @param localPref the LOCAL_PREF required attribute - * @param legacyNlri the legacy NLRI. Encapsulates the NEXT_HOP well-known - * mandatory attribute (mandatory if legacy NLRI is used). - * @param mpNlriReachList the Multiprotocol NLRI attributes - * @throws BgpMessage.BgpParseException - */ - private static void verifyBgpUpdateWellKnownAttributes( - BgpSession bgpSession, - ChannelHandlerContext ctx, - Short origin, - BgpRouteEntry.AsPath asPath, - Long localPref, - MpNlri legacyNlri, - Collection<MpNlri> mpNlriReachList) - throws BgpMessage.BgpParseException { - boolean hasNlri = false; - boolean hasLegacyNlri = false; - - // - // Convenience flags that are used to check for missing attributes. - // - // NOTE: The hasLegacyNlri flag is always set to true if the - // Multiprotocol Extensions are not enabled, even if the UPDATE - // message doesn't contain the legacy NLRI (per RFC 4271). - // - if (!bgpSession.mpExtensions()) { - hasNlri = true; - hasLegacyNlri = true; - } else { - if (!legacyNlri.nlri4.isEmpty()) { - hasNlri = true; - hasLegacyNlri = true; - } - if (!mpNlriReachList.isEmpty()) { - hasNlri = true; - } - } - - // - // Check for Missing Well-known Attributes - // - if (hasNlri && ((origin == null) || (origin == -1))) { - // Missing Attribute Type Code ORIGIN - int type = BgpConstants.Update.Origin.TYPE; - actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type); - String errorMsg = "Missing Well-known Attribute: ORIGIN"; - throw new BgpMessage.BgpParseException(errorMsg); - } - if (hasNlri && (asPath == null)) { - // Missing Attribute Type Code AS_PATH - int type = BgpConstants.Update.AsPath.TYPE; - actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type); - String errorMsg = "Missing Well-known Attribute: AS_PATH"; - throw new BgpMessage.BgpParseException(errorMsg); - } - if (hasNlri && (localPref == null)) { - // Missing Attribute Type Code LOCAL_PREF - // NOTE: Required for iBGP - int type = BgpConstants.Update.LocalPref.TYPE; - actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type); - String errorMsg = "Missing Well-known Attribute: LOCAL_PREF"; - throw new BgpMessage.BgpParseException(errorMsg); - } - if (hasLegacyNlri && (legacyNlri.nextHop4 == null)) { - // Missing Attribute Type Code NEXT_HOP - int type = BgpConstants.Update.NextHop.TYPE; - actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type); - String errorMsg = "Missing Well-known Attribute: NEXT_HOP"; - throw new BgpMessage.BgpParseException(errorMsg); - } - } - - /** - * Verifies the BGP UPDATE Attribute Flags. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @throws BgpMessage.BgpParseException - */ - private static void verifyBgpUpdateAttributeFlags( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - - // - // Assign the Attribute Type Name and the Well-known flag - // - String typeName = "UNKNOWN"; - boolean isWellKnown = false; - switch (attrTypeCode) { - case BgpConstants.Update.Origin.TYPE: - isWellKnown = true; - typeName = "ORIGIN"; - break; - case BgpConstants.Update.AsPath.TYPE: - isWellKnown = true; - typeName = "AS_PATH"; - break; - case BgpConstants.Update.NextHop.TYPE: - isWellKnown = true; - typeName = "NEXT_HOP"; - break; - case BgpConstants.Update.MultiExitDisc.TYPE: - isWellKnown = false; - typeName = "MULTI_EXIT_DISC"; - break; - case BgpConstants.Update.LocalPref.TYPE: - isWellKnown = true; - typeName = "LOCAL_PREF"; - break; - case BgpConstants.Update.AtomicAggregate.TYPE: - isWellKnown = true; - typeName = "ATOMIC_AGGREGATE"; - break; - case BgpConstants.Update.Aggregator.TYPE: - isWellKnown = false; - typeName = "AGGREGATOR"; - break; - case BgpConstants.Update.MpReachNlri.TYPE: - isWellKnown = false; - typeName = "MP_REACH_NLRI"; - break; - case BgpConstants.Update.MpUnreachNlri.TYPE: - isWellKnown = false; - typeName = "MP_UNREACH_NLRI"; - break; - default: - isWellKnown = false; - typeName = "UNKNOWN(" + attrTypeCode + ")"; - break; - } - - // - // Verify the Attribute Flags - // - boolean optionalBit = ((0x80 & attrFlags) != 0); - boolean transitiveBit = ((0x40 & attrFlags) != 0); - boolean partialBit = ((0x20 & attrFlags) != 0); - if ((isWellKnown && optionalBit) || - (isWellKnown && (!transitiveBit)) || - (isWellKnown && partialBit) || - (optionalBit && (!transitiveBit) && partialBit)) { - // - // ERROR: The Optional bit cannot be set for Well-known attributes - // ERROR: The Transtive bit MUST be 1 for well-known attributes - // ERROR: The Partial bit MUST be 0 for well-known attributes - // ERROR: The Partial bit MUST be 0 for optional non-transitive - // attributes - // - actionsBgpUpdateAttributeFlagsError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Attribute Flags Error for " + typeName + ": " + - attrFlags; - throw new BgpMessage.BgpParseException(errorMsg); - } - } - - /** - * Parses BGP UPDATE Attribute Type ORIGIN. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @return the parsed ORIGIN value - * @throws BgpMessage.BgpParseException - */ - private static short parseAttributeTypeOrigin( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - - // Check the Attribute Length - if (attrLen != BgpConstants.Update.Origin.LENGTH) { - // ERROR: Attribute Length Error - actionsBgpUpdateAttributeLengthError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Attribute Length Error"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - message.markReaderIndex(); - short origin = message.readUnsignedByte(); - switch (origin) { - case BgpConstants.Update.Origin.IGP: - // FALLTHROUGH - case BgpConstants.Update.Origin.EGP: - // FALLTHROUGH - case BgpConstants.Update.Origin.INCOMPLETE: - break; - default: - // ERROR: Invalid ORIGIN Attribute - message.resetReaderIndex(); - actionsBgpUpdateInvalidOriginAttribute( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message, - origin); - String errorMsg = "Invalid ORIGIN Attribute: " + origin; - throw new BgpMessage.BgpParseException(errorMsg); - } - - return origin; - } - - /** - * Parses BGP UPDATE Attribute AS Path. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @return the parsed AS Path - * @throws BgpMessage.BgpParseException - */ - private static BgpRouteEntry.AsPath parseAttributeTypeAsPath( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>(); - - // - // Parse the message - // - while (attrLen > 0) { - if (attrLen < 2) { - // ERROR: Malformed AS_PATH - actionsBgpUpdateMalformedAsPath(bgpSession, ctx); - String errorMsg = "Malformed AS Path"; - throw new BgpMessage.BgpParseException(errorMsg); - } - // Get the Path Segment Type and Length (in number of ASes) - short pathSegmentType = message.readUnsignedByte(); - short pathSegmentLength = message.readUnsignedByte(); - attrLen -= 2; - - // Verify the Path Segment Type - switch (pathSegmentType) { - case BgpConstants.Update.AsPath.AS_SET: - // FALLTHROUGH - case BgpConstants.Update.AsPath.AS_SEQUENCE: - // FALLTHROUGH - case BgpConstants.Update.AsPath.AS_CONFED_SEQUENCE: - // FALLTHROUGH - case BgpConstants.Update.AsPath.AS_CONFED_SET: - break; - default: - // ERROR: Invalid Path Segment Type - // - // NOTE: The BGP Spec (RFC 4271) doesn't contain Error Subcode - // for "Invalid Path Segment Type", hence we return - // the error as "Malformed AS_PATH". - // - actionsBgpUpdateMalformedAsPath(bgpSession, ctx); - String errorMsg = - "Invalid AS Path Segment Type: " + pathSegmentType; - throw new BgpMessage.BgpParseException(errorMsg); - } - - // 4-octet AS number handling. - int asPathLen; - if (bgpSession.isAs4OctetCapable()) { - asPathLen = BgpConstants.Update.AS_4OCTET_LENGTH; - } else { - asPathLen = BgpConstants.Update.AS_LENGTH; - } - - // Parse the AS numbers - if (asPathLen * pathSegmentLength > attrLen) { - // ERROR: Malformed AS_PATH - actionsBgpUpdateMalformedAsPath(bgpSession, ctx); - String errorMsg = "Malformed AS Path"; - throw new BgpMessage.BgpParseException(errorMsg); - } - attrLen -= (asPathLen * pathSegmentLength); - ArrayList<Long> segmentAsNumbers = new ArrayList<>(); - while (pathSegmentLength-- > 0) { - long asNumber; - if (asPathLen == BgpConstants.Update.AS_4OCTET_LENGTH) { - asNumber = message.readUnsignedInt(); - } else { - asNumber = message.readUnsignedShort(); - } - segmentAsNumbers.add(asNumber); - } - - BgpRouteEntry.PathSegment pathSegment = - new BgpRouteEntry.PathSegment((byte) pathSegmentType, - segmentAsNumbers); - pathSegments.add(pathSegment); - } - - return new BgpRouteEntry.AsPath(pathSegments); - } - - /** - * Parses BGP UPDATE Attribute Type NEXT_HOP. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @return the parsed NEXT_HOP value - * @throws BgpMessage.BgpParseException - */ - private static Ip4Address parseAttributeTypeNextHop( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - - // Check the Attribute Length - if (attrLen != BgpConstants.Update.NextHop.LENGTH) { - // ERROR: Attribute Length Error - actionsBgpUpdateAttributeLengthError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Attribute Length Error"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - message.markReaderIndex(); - Ip4Address nextHopAddress = - Ip4Address.valueOf((int) message.readUnsignedInt()); - // - // Check whether the NEXT_HOP IP address is semantically correct. - // As per RFC 4271, Section 6.3: - // - // a) It MUST NOT be the IP address of the receiving speaker - // b) In the case of an EBGP .... - // - // Here we check only (a), because (b) doesn't apply for us: all our - // peers are iBGP. - // - if (nextHopAddress.equals(bgpSession.localInfo().ip4Address())) { - // ERROR: Invalid NEXT_HOP Attribute - message.resetReaderIndex(); - actionsBgpUpdateInvalidNextHopAttribute( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message, - nextHopAddress); - String errorMsg = "Invalid NEXT_HOP Attribute: " + nextHopAddress; - throw new BgpMessage.BgpParseException(errorMsg); - } - - return nextHopAddress; - } - - /** - * Parses BGP UPDATE Attribute Type MULTI_EXIT_DISC. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @return the parsed MULTI_EXIT_DISC value - * @throws BgpMessage.BgpParseException - */ - private static long parseAttributeTypeMultiExitDisc( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - - // Check the Attribute Length - if (attrLen != BgpConstants.Update.MultiExitDisc.LENGTH) { - // ERROR: Attribute Length Error - actionsBgpUpdateAttributeLengthError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Attribute Length Error"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - long multiExitDisc = message.readUnsignedInt(); - return multiExitDisc; - } - - /** - * Parses BGP UPDATE Attribute Type LOCAL_PREF. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @return the parsed LOCAL_PREF value - * @throws BgpMessage.BgpParseException - */ - private static long parseAttributeTypeLocalPref( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - - // Check the Attribute Length - if (attrLen != BgpConstants.Update.LocalPref.LENGTH) { - // ERROR: Attribute Length Error - actionsBgpUpdateAttributeLengthError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Attribute Length Error"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - long localPref = message.readUnsignedInt(); - return localPref; - } - - /** - * Parses BGP UPDATE Attribute Type ATOMIC_AGGREGATE. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @throws BgpMessage.BgpParseException - */ - private static void parseAttributeTypeAtomicAggregate( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - - // Check the Attribute Length - if (attrLen != BgpConstants.Update.AtomicAggregate.LENGTH) { - // ERROR: Attribute Length Error - actionsBgpUpdateAttributeLengthError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Attribute Length Error"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - // Nothing to do: this attribute is primarily informational - } - - /** - * Parses BGP UPDATE Attribute Type AGGREGATOR. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @return the parsed AGGREGATOR value: a tuple of <AS-Number, IP-Address> - * @throws BgpMessage.BgpParseException - */ - private static Pair<Long, Ip4Address> parseAttributeTypeAggregator( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - int expectedAttrLen; - - if (bgpSession.isAs4OctetCapable()) { - expectedAttrLen = BgpConstants.Update.Aggregator.AS4_LENGTH; - } else { - expectedAttrLen = BgpConstants.Update.Aggregator.AS2_LENGTH; - } - - // Check the Attribute Length - if (attrLen != expectedAttrLen) { - // ERROR: Attribute Length Error - actionsBgpUpdateAttributeLengthError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Attribute Length Error"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - // The AGGREGATOR AS number - long aggregatorAsNumber; - if (bgpSession.isAs4OctetCapable()) { - aggregatorAsNumber = message.readUnsignedInt(); - } else { - aggregatorAsNumber = message.readUnsignedShort(); - } - // The AGGREGATOR IP address - Ip4Address aggregatorIpAddress = - Ip4Address.valueOf((int) message.readUnsignedInt()); - - Pair<Long, Ip4Address> aggregator = Pair.of(aggregatorAsNumber, - aggregatorIpAddress); - return aggregator; - } - - /** - * Parses BGP UPDATE Attribute Type MP_REACH_NLRI. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @return the parsed MP_REACH_NLRI information if recognized, otherwise - * null - * @throws BgpMessage.BgpParseException - */ - private static MpNlri parseAttributeTypeMpReachNlri( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - int attributeEnd = message.readerIndex() + attrLen; - - // Check the Attribute Length - if (attrLen < BgpConstants.Update.MpReachNlri.MIN_LENGTH) { - // ERROR: Attribute Length Error - actionsBgpUpdateAttributeLengthError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Attribute Length Error"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - message.markReaderIndex(); - int afi = message.readUnsignedShort(); - int safi = message.readUnsignedByte(); - int nextHopLen = message.readUnsignedByte(); - - // - // Verify the AFI/SAFI, and skip the attribute if not recognized. - // NOTE: Currently, we support only IPv4/IPv6 UNICAST - // - if (((afi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4) && - (afi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6)) || - (safi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST)) { - // Skip the attribute - message.resetReaderIndex(); - message.skipBytes(attrLen); - return null; - } - - // - // Verify the next-hop length - // - int expectedNextHopLen = 0; - switch (afi) { - case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4: - expectedNextHopLen = Ip4Address.BYTE_LENGTH; - break; - case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6: - expectedNextHopLen = Ip6Address.BYTE_LENGTH; - break; - default: - // UNREACHABLE - break; - } - if (nextHopLen != expectedNextHopLen) { - // ERROR: Optional Attribute Error - message.resetReaderIndex(); - actionsBgpUpdateOptionalAttributeError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Invalid next-hop network address length. " + - "Received " + nextHopLen + " expected " + expectedNextHopLen; - throw new BgpMessage.BgpParseException(errorMsg); - } - // NOTE: We use "+ 1" to take into account the Reserved field (1 octet) - if (message.readerIndex() + nextHopLen + 1 >= attributeEnd) { - // ERROR: Optional Attribute Error - message.resetReaderIndex(); - actionsBgpUpdateOptionalAttributeError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Malformed next-hop network address"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - // - // Get the Next-hop address, skip the Reserved field, and get the NLRI - // - byte[] nextHopBuffer = new byte[nextHopLen]; - message.readBytes(nextHopBuffer, 0, nextHopLen); - int reserved = message.readUnsignedByte(); - MpNlri mpNlri = new MpNlri(afi, safi); - try { - switch (afi) { - case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4: - // The next-hop address - mpNlri.nextHop4 = Ip4Address.valueOf(nextHopBuffer); - // The NLRI - mpNlri.nlri4 = parsePackedIp4Prefixes( - attributeEnd - message.readerIndex(), - message); - break; - case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6: - // The next-hop address - mpNlri.nextHop6 = Ip6Address.valueOf(nextHopBuffer); - // The NLRI - mpNlri.nlri6 = parsePackedIp6Prefixes( - attributeEnd - message.readerIndex(), - message); - break; - default: - // UNREACHABLE - break; - } - } catch (BgpMessage.BgpParseException e) { - // ERROR: Optional Attribute Error - message.resetReaderIndex(); - actionsBgpUpdateOptionalAttributeError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Malformed network layer reachability information"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - return mpNlri; - } - - /** - * Parses BGP UPDATE Attribute Type MP_UNREACH_NLRI. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message to parse - * @return the parsed MP_UNREACH_NLRI information if recognized, otherwise - * null - * @throws BgpMessage.BgpParseException - */ - private static MpNlri parseAttributeTypeMpUnreachNlri( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - int attributeEnd = message.readerIndex() + attrLen; - - // Check the Attribute Length - if (attrLen < BgpConstants.Update.MpUnreachNlri.MIN_LENGTH) { - // ERROR: Attribute Length Error - actionsBgpUpdateAttributeLengthError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Attribute Length Error"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - message.markReaderIndex(); - int afi = message.readUnsignedShort(); - int safi = message.readUnsignedByte(); - - // - // Verify the AFI/SAFI, and skip the attribute if not recognized. - // NOTE: Currently, we support only IPv4/IPv6 UNICAST - // - if (((afi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4) && - (afi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6)) || - (safi != BgpConstants.Open.Capabilities.MultiprotocolExtensions.SAFI_UNICAST)) { - // Skip the attribute - message.resetReaderIndex(); - message.skipBytes(attrLen); - return null; - } - - // - // Get the Withdrawn Routes - // - MpNlri mpNlri = new MpNlri(afi, safi); - try { - switch (afi) { - case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV4: - // The Withdrawn Routes - mpNlri.nlri4 = parsePackedIp4Prefixes( - attributeEnd - message.readerIndex(), - message); - break; - case BgpConstants.Open.Capabilities.MultiprotocolExtensions.AFI_IPV6: - // The Withdrawn Routes - mpNlri.nlri6 = parsePackedIp6Prefixes( - attributeEnd - message.readerIndex(), - message); - break; - default: - // UNREACHABLE - break; - } - } catch (BgpMessage.BgpParseException e) { - // ERROR: Optional Attribute Error - message.resetReaderIndex(); - actionsBgpUpdateOptionalAttributeError( - bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message); - String errorMsg = "Malformed withdrawn routes"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - return mpNlri; - } - - /** - * Parses a message that contains encoded IPv4 network prefixes. - * <p> - * The IPv4 prefixes are encoded in the form: - * <Length, Prefix> where Length is the length in bits of the IPv4 prefix, - * and Prefix is the IPv4 prefix (padded with trailing bits to the end - * of an octet). - * - * @param totalLength the total length of the data to parse - * @param message the message with data to parse - * @return a collection of parsed IPv4 network prefixes - * @throws BgpMessage.BgpParseException - */ - private static Collection<Ip4Prefix> parsePackedIp4Prefixes( - int totalLength, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - Collection<Ip4Prefix> result = new ArrayList<>(); - - if (totalLength == 0) { - return result; - } - - // Parse the data - byte[] buffer = new byte[Ip4Address.BYTE_LENGTH]; - int dataEnd = message.readerIndex() + totalLength; - while (message.readerIndex() < dataEnd) { - int prefixBitlen = message.readUnsignedByte(); - int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up - if (message.readerIndex() + prefixBytelen > dataEnd) { - String errorMsg = "Malformed Network Prefixes"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - message.readBytes(buffer, 0, prefixBytelen); - Ip4Prefix prefix = Ip4Prefix.valueOf(Ip4Address.valueOf(buffer), - prefixBitlen); - result.add(prefix); - } - - return result; - } - - /** - * Parses a message that contains encoded IPv6 network prefixes. - * <p> - * The IPv6 prefixes are encoded in the form: - * <Length, Prefix> where Length is the length in bits of the IPv6 prefix, - * and Prefix is the IPv6 prefix (padded with trailing bits to the end - * of an octet). - * - * @param totalLength the total length of the data to parse - * @param message the message with data to parse - * @return a collection of parsed IPv6 network prefixes - * @throws BgpMessage.BgpParseException - */ - private static Collection<Ip6Prefix> parsePackedIp6Prefixes( - int totalLength, - ChannelBuffer message) - throws BgpMessage.BgpParseException { - Collection<Ip6Prefix> result = new ArrayList<>(); - - if (totalLength == 0) { - return result; - } - - // Parse the data - byte[] buffer = new byte[Ip6Address.BYTE_LENGTH]; - int dataEnd = message.readerIndex() + totalLength; - while (message.readerIndex() < dataEnd) { - int prefixBitlen = message.readUnsignedByte(); - int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up - if (message.readerIndex() + prefixBytelen > dataEnd) { - String errorMsg = "Malformed Network Prefixes"; - throw new BgpMessage.BgpParseException(errorMsg); - } - - message.readBytes(buffer, 0, prefixBytelen); - Ip6Prefix prefix = Ip6Prefix.valueOf(Ip6Address.valueOf(buffer), - prefixBitlen); - result.add(prefix); - } - - return result; - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Invalid Network Field Error: send NOTIFICATION and close the channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - */ - private static void actionsBgpUpdateInvalidNetworkField( - BgpSession bgpSession, - ChannelHandlerContext ctx) { - log.debug("BGP RX UPDATE Error from {}: Invalid Network Field", - bgpSession.remoteInfo().address()); - - // - // ERROR: Invalid Network Field - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = BgpConstants.Notifications.UpdateMessageError.INVALID_NETWORK_FIELD; - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - null); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Malformed Attribute List Error: send NOTIFICATION and close the channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - */ - private static void actionsBgpUpdateMalformedAttributeList( - BgpSession bgpSession, - ChannelHandlerContext ctx) { - log.debug("BGP RX UPDATE Error from {}: Malformed Attribute List", - bgpSession.remoteInfo().address()); - - // - // ERROR: Malformed Attribute List - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = BgpConstants.Notifications.UpdateMessageError.MALFORMED_ATTRIBUTE_LIST; - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - null); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Missing Well-known Attribute Error: send NOTIFICATION and close the - * channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param missingAttrTypeCode the missing attribute type code - */ - private static void actionsBgpUpdateMissingWellKnownAttribute( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int missingAttrTypeCode) { - log.debug("BGP RX UPDATE Error from {}: Missing Well-known Attribute: {}", - bgpSession.remoteInfo().address(), missingAttrTypeCode); - - // - // ERROR: Missing Well-known Attribute - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = BgpConstants.Notifications.UpdateMessageError.MISSING_WELL_KNOWN_ATTRIBUTE; - ChannelBuffer data = ChannelBuffers.buffer(1); - data.writeByte(missingAttrTypeCode); - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - data); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Invalid ORIGIN Attribute Error: send NOTIFICATION and close the channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message with the data - * @param origin the ORIGIN attribute value - */ - private static void actionsBgpUpdateInvalidOriginAttribute( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message, - short origin) { - log.debug("BGP RX UPDATE Error from {}: Invalid ORIGIN Attribute", - bgpSession.remoteInfo().address()); - - // - // ERROR: Invalid ORIGIN Attribute - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = BgpConstants.Notifications.UpdateMessageError.INVALID_ORIGIN_ATTRIBUTE; - ChannelBuffer data = - prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen, - attrFlags, message); - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - data); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Attribute Flags Error: send NOTIFICATION and close the channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message with the data - */ - private static void actionsBgpUpdateAttributeFlagsError( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) { - log.debug("BGP RX UPDATE Error from {}: Attribute Flags Error", - bgpSession.remoteInfo().address()); - - // - // ERROR: Attribute Flags Error - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = BgpConstants.Notifications.UpdateMessageError.ATTRIBUTE_FLAGS_ERROR; - ChannelBuffer data = - prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen, - attrFlags, message); - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - data); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Invalid NEXT_HOP Attribute Error: send NOTIFICATION and close the - * channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message with the data - * @param nextHop the NEXT_HOP attribute value - */ - private static void actionsBgpUpdateInvalidNextHopAttribute( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message, - Ip4Address nextHop) { - log.debug("BGP RX UPDATE Error from {}: Invalid NEXT_HOP Attribute {}", - bgpSession.remoteInfo().address(), nextHop); - - // - // ERROR: Invalid NEXT_HOP Attribute - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = BgpConstants.Notifications.UpdateMessageError.INVALID_NEXT_HOP_ATTRIBUTE; - ChannelBuffer data = - prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen, - attrFlags, message); - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - data); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Unrecognized Well-known Attribute Error: send NOTIFICATION and close - * the channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message with the data - */ - private static void actionsBgpUpdateUnrecognizedWellKnownAttribute( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) { - log.debug("BGP RX UPDATE Error from {}: " + - "Unrecognized Well-known Attribute Error: {}", - bgpSession.remoteInfo().address(), attrTypeCode); - - // - // ERROR: Unrecognized Well-known Attribute - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = - BgpConstants.Notifications.UpdateMessageError.UNRECOGNIZED_WELL_KNOWN_ATTRIBUTE; - ChannelBuffer data = - prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen, - attrFlags, message); - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - data); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Optional Attribute Error: send NOTIFICATION and close - * the channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message with the data - */ - private static void actionsBgpUpdateOptionalAttributeError( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) { - log.debug("BGP RX UPDATE Error from {}: Optional Attribute Error: {}", - bgpSession.remoteInfo().address(), attrTypeCode); - - // - // ERROR: Optional Attribute Error - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = - BgpConstants.Notifications.UpdateMessageError.OPTIONAL_ATTRIBUTE_ERROR; - ChannelBuffer data = - prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen, - attrFlags, message); - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - data); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Attribute Length Error: send NOTIFICATION and close the channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message with the data - */ - private static void actionsBgpUpdateAttributeLengthError( - BgpSession bgpSession, - ChannelHandlerContext ctx, - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) { - log.debug("BGP RX UPDATE Error from {}: Attribute Length Error", - bgpSession.remoteInfo().address()); - - // - // ERROR: Attribute Length Error - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = BgpConstants.Notifications.UpdateMessageError.ATTRIBUTE_LENGTH_ERROR; - ChannelBuffer data = - prepareBgpUpdateNotificationDataPayload(attrTypeCode, attrLen, - attrFlags, message); - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - data); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Applies the appropriate actions after detecting BGP UPDATE - * Malformed AS_PATH Error: send NOTIFICATION and close the channel. - * - * @param bgpSession the BGP Session to use - * @param ctx the Channel Handler Context - */ - private static void actionsBgpUpdateMalformedAsPath( - BgpSession bgpSession, - ChannelHandlerContext ctx) { - log.debug("BGP RX UPDATE Error from {}: Malformed AS Path", - bgpSession.remoteInfo().address()); - - // - // ERROR: Malformed AS_PATH - // - // Send NOTIFICATION and close the connection - int errorCode = BgpConstants.Notifications.UpdateMessageError.ERROR_CODE; - int errorSubcode = BgpConstants.Notifications.UpdateMessageError.MALFORMED_AS_PATH; - ChannelBuffer txMessage = - BgpNotification.prepareBgpNotification(errorCode, errorSubcode, - null); - ctx.getChannel().write(txMessage); - bgpSession.closeSession(ctx); - } - - /** - * Prepares BGP UPDATE Notification data payload. - * - * @param attrTypeCode the attribute type code - * @param attrLen the attribute length (in octets) - * @param attrFlags the attribute flags - * @param message the message with the data - * @return the buffer with the data payload for the BGP UPDATE Notification - */ - private static ChannelBuffer prepareBgpUpdateNotificationDataPayload( - int attrTypeCode, - int attrLen, - int attrFlags, - ChannelBuffer message) { - // Compute the attribute length field octets - boolean extendedLengthBit = ((0x10 & attrFlags) != 0); - int attrLenOctets = 1; - if (extendedLengthBit) { - attrLenOctets = 2; - } - ChannelBuffer data = - ChannelBuffers.buffer(attrLen + attrLenOctets + 1); - data.writeByte(attrTypeCode); - if (extendedLengthBit) { - data.writeShort(attrLen); - } else { - data.writeByte(attrLen); - } - data.writeBytes(message, attrLen); - return data; - } - - /** - * Helper class for storing Multiprotocol Network Layer Reachability - * information. - */ - private static final class MpNlri { - private final int afi; - private final int safi; - private Ip4Address nextHop4; - private Ip6Address nextHop6; - private Collection<Ip4Prefix> nlri4 = new ArrayList<>(); - private Collection<Ip6Prefix> nlri6 = new ArrayList<>(); - - /** - * Constructor. - * - * @param afi the Address Family Identifier - * @param safi the Subsequent Address Family Identifier - */ - private MpNlri(int afi, int safi) { - this.afi = afi; - this.safi = safi; - } - } - - /** - * Helper class for storing decoded BGP routing information. - */ - private static final class DecodedBgpRoutes { - private final Map<Ip4Prefix, BgpRouteEntry> addedUnicastRoutes4 = - new HashMap<>(); - private final Map<Ip6Prefix, BgpRouteEntry> addedUnicastRoutes6 = - new HashMap<>(); - private final Map<Ip4Prefix, BgpRouteEntry> deletedUnicastRoutes4 = - new HashMap<>(); - private final Map<Ip6Prefix, BgpRouteEntry> deletedUnicastRoutes6 = - new HashMap<>(); - } -} |