/*
 * Copyright 2014 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.sdnip.bgp;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

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.Ip6Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Prefix;
import org.onosproject.sdnip.bgp.BgpConstants.Notifications.UpdateMessageError;
import org.onosproject.sdnip.bgp.BgpConstants.Open.Capabilities.MultiprotocolExtensions;
import org.onosproject.sdnip.bgp.BgpConstants.Update;
import org.onosproject.sdnip.bgp.BgpConstants.Update.AsPath;
import org.onosproject.sdnip.bgp.BgpMessage.BgpParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 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.getRemoteAddress(), 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.getRemoteAddress());

        //
        // 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 (BgpParseException e) {
            // ERROR: Invalid Network Field
            log.debug("Exception parsing Withdrawn Prefixes from BGP peer {}: ",
                      bgpSession.getRemoteBgpId(), e);
            actionsBgpUpdateInvalidNetworkField(bgpSession, ctx);
            return;
        }
        for (Ip4Prefix prefix : withdrawnPrefixes) {
            log.debug("BGP RX UPDATE message WITHDRAWN from {}: {}",
                      bgpSession.getRemoteAddress(), prefix);
            BgpRouteEntry bgpRouteEntry = bgpSession.bgpRibIn4().get(prefix);
            if (bgpRouteEntry != null) {
                decodedBgpRoutes.deletedUnicastRoutes4.put(prefix,
                                                           bgpRouteEntry);
            }
        }

        //
        // Parse the Path Attributes
        //
        try {
            parsePathAttributes(bgpSession, ctx, message, decodedBgpRoutes);
        } catch (BgpParseException e) {
            log.debug("Exception parsing Path Attributes from BGP peer {}: ",
                      bgpSession.getRemoteBgpId(), e);
            // NOTE: The session was already closed, so nothing else to do
            return;
        }

        //
        // Update the BGP RIB-IN
        //
        Collection<BgpRouteEntry> bgpRoutes;
        //
        bgpRoutes = decodedBgpRoutes.deletedUnicastRoutes4.values();
        for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
            bgpSession.bgpRibIn4().remove(bgpRouteEntry.prefix());
        }
        //
        bgpRoutes = decodedBgpRoutes.addedUnicastRoutes4.values();
        for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
            bgpSession.bgpRibIn4().put(bgpRouteEntry.prefix(), bgpRouteEntry);
        }
        //
        bgpRoutes = decodedBgpRoutes.deletedUnicastRoutes6.values();
        for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
            bgpSession.bgpRibIn6().remove(bgpRouteEntry.prefix());
        }
        //
        bgpRoutes = decodedBgpRoutes.addedUnicastRoutes6.values();
        // TODO: fix/enable for IPv6
        /*
        for (BgpRouteEntry bgpRouteEntry : bgpRoutes) {
            bgpSession.bgpRibIn6().put(bgpRouteEntry.prefix(), bgpRouteEntry);
        }
        */

        //
        // Push the updates to the BGP Merged RIB
        //
        BgpSessionManager.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 BgpParseException
     */
    // CHECKSTYLE IGNORE MethodLength FOR NEXT 300 LINES
    private static void parsePathAttributes(
                                        BgpSession bgpSession,
                                        ChannelHandlerContext ctx,
                                        ChannelBuffer message,
                                        DecodedBgpRoutes decodedBgpRoutes)
        throws 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(MultiprotocolExtensions.AFI_IPV4,
                                       MultiprotocolExtensions.SAFI_UNICAST);
        long multiExitDisc =                    // Optional
            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 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 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 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 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 Update.Origin.TYPE:
                // Attribute Type Code ORIGIN
                origin = parseAttributeTypeOrigin(bgpSession, ctx,
                                                  attrTypeCode, attrLen,
                                                  attrFlags, message);
                break;

            case Update.AsPath.TYPE:
                // Attribute Type Code AS_PATH
                asPath = parseAttributeTypeAsPath(bgpSession, ctx,
                                                  attrTypeCode, attrLen,
                                                  attrFlags, message);
                break;

            case Update.NextHop.TYPE:
                // Attribute Type Code NEXT_HOP
                legacyNlri.nextHop4 =
                    parseAttributeTypeNextHop(bgpSession, ctx,
                                              attrTypeCode, attrLen,
                                              attrFlags, message);
                break;

            case Update.MultiExitDisc.TYPE:
                // Attribute Type Code MULTI_EXIT_DISC
                multiExitDisc =
                    parseAttributeTypeMultiExitDisc(bgpSession, ctx,
                                                    attrTypeCode, attrLen,
                                                    attrFlags, message);
                break;

            case Update.LocalPref.TYPE:
                // Attribute Type Code LOCAL_PREF
                localPref =
                    parseAttributeTypeLocalPref(bgpSession, ctx,
                                                attrTypeCode, attrLen,
                                                attrFlags, message);
                break;

            case 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 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 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 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 BgpParseException(errorMsg);
                }

                // Skip the data from the unrecognized attribute
                log.debug("BGP RX UPDATE message from {}: " +
                          "Unrecognized Attribute Type {}",
                          bgpSession.getRemoteAddress(), 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 (BgpParseException e) {
            // ERROR: Invalid Network Field
            log.debug("Exception parsing NLRI from BGP peer {}: ",
                      bgpSession.getRemoteBgpId(), 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.bgpRibIn4().get(prefix);
                if (bgpRouteEntry != null) {
                    decodedBgpRoutes.deletedUnicastRoutes4.put(prefix,
                                                               bgpRouteEntry);
                }
            }

            // The deleted IPv6 routes
            for (Ip6Prefix prefix : mpNlri.nlri6) {
                bgpRouteEntry = bgpSession.bgpRibIn6().get(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.getLocalAs())) {
                    log.debug("BGP RX UPDATE message IGNORED from {}: {} " +
                              "nextHop {}: contains AS Path loop",
                              bgpSession.getRemoteAddress(), prefix,
                              mpNlri.nextHop4);
                    continue;
                } else {
                    log.debug("BGP RX UPDATE message ADDED from {}: {} nextHop {}",
                              bgpSession.getRemoteAddress(), prefix,
                              mpNlri.nextHop4);
                }
                // Remove from the collection of deleted routes
                decodedBgpRoutes.deletedUnicastRoutes4.remove(prefix);
                decodedBgpRoutes.addedUnicastRoutes4.put(prefix,
                                                         bgpRouteEntry);
            }

            // The added IPv6 routes
            // TODO: fix/enable for IPv6
            /*
            for (Ip6Prefix prefix : mpNlri.nlri6) {
                bgpRouteEntry =
                    new BgpRouteEntry(bgpSession, prefix, mpNlri.nextHop6,
                                      origin.byteValue(), asPath, localPref);
                bgpRouteEntry.setMultiExitDisc(multiExitDisc);
                if (bgpRouteEntry.hasAsPathLoop(bgpSession.getLocalAs())) {
                    log.debug("BGP RX UPDATE message IGNORED from {}: {} " +
                              "nextHop {}: contains AS Path loop",
                              bgpSession.getRemoteAddress(), prefix,
                              mpNlri.nextHop6);
                    continue;
                } else {
                    log.debug("BGP RX UPDATE message ADDED from {}: {} nextHop {}",
                              bgpSession.getRemoteAddress(), 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 BgpParseException
     */
    private static void verifyBgpUpdateWellKnownAttributes(
                                BgpSession bgpSession,
                                ChannelHandlerContext ctx,
                                Short origin,
                                BgpRouteEntry.AsPath asPath,
                                Long localPref,
                                MpNlri legacyNlri,
                                Collection<MpNlri> mpNlriReachList)
        throws 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.getMpExtensions()) {
            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 = Update.Origin.TYPE;
            actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
            String errorMsg = "Missing Well-known Attribute: ORIGIN";
            throw new BgpParseException(errorMsg);
        }
        if (hasNlri && (asPath == null)) {
            // Missing Attribute Type Code AS_PATH
            int type = Update.AsPath.TYPE;
            actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
            String errorMsg = "Missing Well-known Attribute: AS_PATH";
            throw new BgpParseException(errorMsg);
        }
        if (hasNlri && (localPref == null)) {
            // Missing Attribute Type Code LOCAL_PREF
            // NOTE: Required for iBGP
            int type = Update.LocalPref.TYPE;
            actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
            String errorMsg = "Missing Well-known Attribute: LOCAL_PREF";
            throw new BgpParseException(errorMsg);
        }
        if (hasLegacyNlri && (legacyNlri.nextHop4 == null)) {
            // Missing Attribute Type Code NEXT_HOP
            int type = Update.NextHop.TYPE;
            actionsBgpUpdateMissingWellKnownAttribute(bgpSession, ctx, type);
            String errorMsg = "Missing Well-known Attribute: NEXT_HOP";
            throw new 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 BgpParseException
     */
    private static void verifyBgpUpdateAttributeFlags(
                                BgpSession bgpSession,
                                ChannelHandlerContext ctx,
                                int attrTypeCode,
                                int attrLen,
                                int attrFlags,
                                ChannelBuffer message)
        throws BgpParseException {

        //
        // Assign the Attribute Type Name and the Well-known flag
        //
        String typeName = "UNKNOWN";
        boolean isWellKnown = false;
        switch (attrTypeCode) {
        case Update.Origin.TYPE:
            isWellKnown = true;
            typeName = "ORIGIN";
            break;
        case Update.AsPath.TYPE:
            isWellKnown = true;
            typeName = "AS_PATH";
            break;
        case Update.NextHop.TYPE:
            isWellKnown = true;
            typeName = "NEXT_HOP";
            break;
        case Update.MultiExitDisc.TYPE:
            isWellKnown = false;
            typeName = "MULTI_EXIT_DISC";
            break;
        case Update.LocalPref.TYPE:
            isWellKnown = true;
            typeName = "LOCAL_PREF";
            break;
        case Update.AtomicAggregate.TYPE:
            isWellKnown = true;
            typeName = "ATOMIC_AGGREGATE";
            break;
        case Update.Aggregator.TYPE:
            isWellKnown = false;
            typeName = "AGGREGATOR";
            break;
        case Update.MpReachNlri.TYPE:
            isWellKnown = false;
            typeName = "MP_REACH_NLRI";
            break;
        case 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 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 BgpParseException
     */
    private static short parseAttributeTypeOrigin(
                                BgpSession bgpSession,
                                ChannelHandlerContext ctx,
                                int attrTypeCode,
                                int attrLen,
                                int attrFlags,
                                ChannelBuffer message)
        throws BgpParseException {

        // Check the Attribute Length
        if (attrLen != Update.Origin.LENGTH) {
            // ERROR: Attribute Length Error
            actionsBgpUpdateAttributeLengthError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Attribute Length Error";
            throw new BgpParseException(errorMsg);
        }

        message.markReaderIndex();
        short origin = message.readUnsignedByte();
        switch (origin) {
        case Update.Origin.IGP:
            // FALLTHROUGH
        case Update.Origin.EGP:
            // FALLTHROUGH
        case 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 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 BgpParseException
     */
    private static BgpRouteEntry.AsPath parseAttributeTypeAsPath(
                                                BgpSession bgpSession,
                                                ChannelHandlerContext ctx,
                                                int attrTypeCode,
                                                int attrLen,
                                                int attrFlags,
                                                ChannelBuffer message)
        throws 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 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 Update.AsPath.AS_SET:
                // FALLTHROUGH
            case Update.AsPath.AS_SEQUENCE:
                // FALLTHROUGH
            case Update.AsPath.AS_CONFED_SEQUENCE:
                // FALLTHROUGH
            case 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 BgpParseException(errorMsg);
            }

            // 4-octet AS number handling.
            int asPathLen;
            if (bgpSession.isAs4OctetCapable()) {
                asPathLen = AsPath.AS_4OCTET_LENGTH;
            } else {
                asPathLen = AsPath.AS_LENGTH;
            }

            // Parse the AS numbers
            if (asPathLen * pathSegmentLength > attrLen) {
                // ERROR: Malformed AS_PATH
                actionsBgpUpdateMalformedAsPath(bgpSession, ctx);
                String errorMsg = "Malformed AS Path";
                throw new BgpParseException(errorMsg);
            }
            attrLen -= (asPathLen * pathSegmentLength);
            ArrayList<Long> segmentAsNumbers = new ArrayList<>();
            while (pathSegmentLength-- > 0) {
                long asNumber;
                if (asPathLen == AsPath.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 BgpParseException
     */
    private static Ip4Address parseAttributeTypeNextHop(
                                        BgpSession bgpSession,
                                        ChannelHandlerContext ctx,
                                        int attrTypeCode,
                                        int attrLen,
                                        int attrFlags,
                                        ChannelBuffer message)
        throws BgpParseException {

        // Check the Attribute Length
        if (attrLen != Update.NextHop.LENGTH) {
            // ERROR: Attribute Length Error
            actionsBgpUpdateAttributeLengthError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Attribute Length Error";
            throw new 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.getLocalIp4Address())) {
            // ERROR: Invalid NEXT_HOP Attribute
            message.resetReaderIndex();
            actionsBgpUpdateInvalidNextHopAttribute(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message,
                nextHopAddress);
            String errorMsg = "Invalid NEXT_HOP Attribute: " + nextHopAddress;
            throw new 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 BgpParseException
     */
    private static long parseAttributeTypeMultiExitDisc(
                                BgpSession bgpSession,
                                ChannelHandlerContext ctx,
                                int attrTypeCode,
                                int attrLen,
                                int attrFlags,
                                ChannelBuffer message)
        throws BgpParseException {

        // Check the Attribute Length
        if (attrLen != Update.MultiExitDisc.LENGTH) {
            // ERROR: Attribute Length Error
            actionsBgpUpdateAttributeLengthError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Attribute Length Error";
            throw new 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 BgpParseException
     */
    private static long parseAttributeTypeLocalPref(
                                BgpSession bgpSession,
                                ChannelHandlerContext ctx,
                                int attrTypeCode,
                                int attrLen,
                                int attrFlags,
                                ChannelBuffer message)
        throws BgpParseException {

        // Check the Attribute Length
        if (attrLen != Update.LocalPref.LENGTH) {
            // ERROR: Attribute Length Error
            actionsBgpUpdateAttributeLengthError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Attribute Length Error";
            throw new 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 BgpParseException
     */
    private static void parseAttributeTypeAtomicAggregate(
                                BgpSession bgpSession,
                                ChannelHandlerContext ctx,
                                int attrTypeCode,
                                int attrLen,
                                int attrFlags,
                                ChannelBuffer message)
        throws BgpParseException {

        // Check the Attribute Length
        if (attrLen != Update.AtomicAggregate.LENGTH) {
            // ERROR: Attribute Length Error
            actionsBgpUpdateAttributeLengthError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Attribute Length Error";
            throw new 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 BgpParseException
     */
    private static Pair<Long, Ip4Address> parseAttributeTypeAggregator(
                                                BgpSession bgpSession,
                                                ChannelHandlerContext ctx,
                                                int attrTypeCode,
                                                int attrLen,
                                                int attrFlags,
                                                ChannelBuffer message)
        throws BgpParseException {

        // Check the Attribute Length
        if (attrLen != Update.Aggregator.LENGTH) {
            // ERROR: Attribute Length Error
            actionsBgpUpdateAttributeLengthError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Attribute Length Error";
            throw new BgpParseException(errorMsg);
        }

        // The AGGREGATOR AS number
        long 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 BgpParseException
     */
    private static MpNlri parseAttributeTypeMpReachNlri(
                                                BgpSession bgpSession,
                                                ChannelHandlerContext ctx,
                                                int attrTypeCode,
                                                int attrLen,
                                                int attrFlags,
                                                ChannelBuffer message)
        throws BgpParseException {
        int attributeEnd = message.readerIndex() + attrLen;

        // Check the Attribute Length
        if (attrLen < Update.MpReachNlri.MIN_LENGTH) {
            // ERROR: Attribute Length Error
            actionsBgpUpdateAttributeLengthError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Attribute Length Error";
            throw new 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 != MultiprotocolExtensions.AFI_IPV4) &&
             (afi != MultiprotocolExtensions.AFI_IPV6)) ||
            (safi != MultiprotocolExtensions.SAFI_UNICAST)) {
            // Skip the attribute
            message.resetReaderIndex();
            message.skipBytes(attrLen);
            return null;
        }

        //
        // Verify the next-hop length
        //
        int expectedNextHopLen = 0;
        switch (afi) {
        case MultiprotocolExtensions.AFI_IPV4:
            expectedNextHopLen = Ip4Address.BYTE_LENGTH;
            break;
        case 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 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 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 MultiprotocolExtensions.AFI_IPV4:
                // The next-hop address
                mpNlri.nextHop4 = Ip4Address.valueOf(nextHopBuffer);
                // The NLRI
                mpNlri.nlri4 = parsePackedIp4Prefixes(
                                        attributeEnd - message.readerIndex(),
                                        message);
                break;
            case 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 (BgpParseException e) {
            // ERROR: Optional Attribute Error
            message.resetReaderIndex();
            actionsBgpUpdateOptionalAttributeError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Malformed network layer reachability information";
            throw new 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 BgpParseException
     */
    private static MpNlri parseAttributeTypeMpUnreachNlri(
                                                BgpSession bgpSession,
                                                ChannelHandlerContext ctx,
                                                int attrTypeCode,
                                                int attrLen,
                                                int attrFlags,
                                                ChannelBuffer message)
        throws BgpParseException {
        int attributeEnd = message.readerIndex() + attrLen;

        // Check the Attribute Length
        if (attrLen < Update.MpUnreachNlri.MIN_LENGTH) {
            // ERROR: Attribute Length Error
            actionsBgpUpdateAttributeLengthError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Attribute Length Error";
            throw new 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 != MultiprotocolExtensions.AFI_IPV4) &&
             (afi != MultiprotocolExtensions.AFI_IPV6)) ||
            (safi != 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 MultiprotocolExtensions.AFI_IPV4:
                // The Withdrawn Routes
                mpNlri.nlri4 = parsePackedIp4Prefixes(
                                        attributeEnd - message.readerIndex(),
                                        message);
                break;
            case MultiprotocolExtensions.AFI_IPV6:
                // The Withdrawn Routes
                mpNlri.nlri6 = parsePackedIp6Prefixes(
                                        attributeEnd - message.readerIndex(),
                                        message);
                break;
            default:
                // UNREACHABLE
                break;
            }
        } catch (BgpParseException e) {
            // ERROR: Optional Attribute Error
            message.resetReaderIndex();
            actionsBgpUpdateOptionalAttributeError(
                bgpSession, ctx, attrTypeCode, attrLen, attrFlags, message);
            String errorMsg = "Malformed withdrawn routes";
            throw new 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 BgpParseException
     */
    private static Collection<Ip4Prefix> parsePackedIp4Prefixes(
                                                int totalLength,
                                                ChannelBuffer message)
        throws 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 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 BgpParseException
     */
    private static Collection<Ip6Prefix> parsePackedIp6Prefixes(
                                                int totalLength,
                                                ChannelBuffer message)
        throws 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 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.getRemoteAddress());

        //
        // ERROR: Invalid Network Field
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode = 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.getRemoteAddress());

        //
        // ERROR: Malformed Attribute List
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode = 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.getRemoteAddress(), missingAttrTypeCode);

        //
        // ERROR: Missing Well-known Attribute
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode = 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.getRemoteAddress());

        //
        // ERROR: Invalid ORIGIN Attribute
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode = 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.getRemoteAddress());

        //
        // ERROR: Attribute Flags Error
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode = 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.getRemoteAddress(), nextHop);

        //
        // ERROR: Invalid NEXT_HOP Attribute
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode = 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.getRemoteAddress(), attrTypeCode);

        //
        // ERROR: Unrecognized Well-known Attribute
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode =
            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.getRemoteAddress(), attrTypeCode);

        //
        // ERROR: Optional Attribute Error
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode =
            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.getRemoteAddress());

        //
        // ERROR: Attribute Length Error
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode = 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.getRemoteAddress());

        //
        // ERROR: Malformed AS_PATH
        //
        // Send NOTIFICATION and close the connection
        int errorCode = UpdateMessageError.ERROR_CODE;
        int errorSubcode = 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<>();
    }
}
