Search in sources :

Example 11 with Ip6Prefix

use of org.onlab.packet.Ip6Prefix in project onos by opennetworkinglab.

the class BgpUpdate method processBgpUpdate.

/**
 * 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);
        }
    }
    // 
    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;
    }
    // 
    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(decodedBgpRoutes.addedUnicastRoutes4.values(), decodedBgpRoutes.deletedUnicastRoutes4.values());
    bgpRouteSelector.routeUpdates(decodedBgpRoutes.addedUnicastRoutes6.values(), decodedBgpRoutes.deletedUnicastRoutes6.values());
    // Start the Session Timeout timer
    bgpSession.restartSessionTimeoutTimer(ctx);
}
Also used : Ip6Prefix(org.onlab.packet.Ip6Prefix) Ip4Prefix(org.onlab.packet.Ip4Prefix) ChannelBuffer(org.jboss.netty.buffer.ChannelBuffer)

Example 12 with Ip6Prefix

use of org.onlab.packet.Ip6Prefix in project onos by opennetworkinglab.

the class BgpUpdate method parsePathAttributes.

/**
 * 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
    // 
    // Mandatory
    Short origin = -1;
    // Mandatory
    BgpRouteEntry.AsPath asPath = null;
    // 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);
    // Optional
    long multiExitDisc = BgpConstants.Update.MultiExitDisc.LOWEST_MULTI_EXIT_DISC;
    // Mandatory
    Long localPref = null;
    // Optional: unused
    Long aggregatorAsNumber = null;
    // Optional: unused
    Ip4Address aggregatorIpAddress = null;
    // Optional
    Collection<MpNlri> mpNlriReachList = new ArrayList<>();
    // Optional
    Collection<MpNlri> mpNlriUnreachList = new ArrayList<>();
    // 
    // 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);
        // 
        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);
    // 
    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);
        }
    }
}
Also used : Ip4Address(org.onlab.packet.Ip4Address) ArrayList(java.util.ArrayList) Ip6Prefix(org.onlab.packet.Ip6Prefix) Ip4Prefix(org.onlab.packet.Ip4Prefix)

Example 13 with Ip6Prefix

use of org.onlab.packet.Ip6Prefix in project onos by opennetworkinglab.

the class BgpUpdate method parsePackedIp6Prefixes.

/**
 * 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();
        // Round-up
        int prefixBytelen = (prefixBitlen + 7) / 8;
        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;
}
Also used : Ip6Prefix(org.onlab.packet.Ip6Prefix) ArrayList(java.util.ArrayList)

Example 14 with Ip6Prefix

use of org.onlab.packet.Ip6Prefix in project onos by opennetworkinglab.

the class RouteEntryTest method testInvalidConstructorNullIpv6Prefix.

/**
 * Tests invalid class constructor for null IPv6 prefix.
 */
@Test(expected = NullPointerException.class)
public void testInvalidConstructorNullIpv6Prefix() {
    Ip6Prefix prefix = null;
    Ip6Address nextHop = Ip6Address.valueOf("2000::1");
    new RouteEntry(prefix, nextHop);
}
Also used : Ip6Prefix(org.onlab.packet.Ip6Prefix) Ip6Address(org.onlab.packet.Ip6Address) Test(org.junit.Test)

Example 15 with Ip6Prefix

use of org.onlab.packet.Ip6Prefix in project onos by opennetworkinglab.

the class RouteEntryTest method testToString.

/**
 * Tests object string representation.
 */
@Test
public void testToString() {
    Ip4Prefix prefix = Ip4Prefix.valueOf("1.2.3.0/24");
    Ip4Address nextHop = Ip4Address.valueOf("5.6.7.8");
    RouteEntry routeEntry = new RouteEntry(prefix, nextHop);
    assertThat(routeEntry.toString(), is("RouteEntry{prefix=1.2.3.0/24, nextHop=5.6.7.8}"));
    Ip6Prefix prefix6 = Ip6Prefix.valueOf("1000::/64");
    Ip6Address nextHop6 = Ip6Address.valueOf("2000::1");
    RouteEntry routeEntry6 = new RouteEntry(prefix6, nextHop6);
    assertThat(routeEntry6.toString(), is("RouteEntry{prefix=1000::/64, nextHop=2000::1}"));
}
Also used : Ip6Prefix(org.onlab.packet.Ip6Prefix) Ip6Address(org.onlab.packet.Ip6Address) Ip4Address(org.onlab.packet.Ip4Address) Ip4Prefix(org.onlab.packet.Ip4Prefix) Test(org.junit.Test)

Aggregations

Ip6Prefix (org.onlab.packet.Ip6Prefix)15 Ip4Prefix (org.onlab.packet.Ip4Prefix)10 Ip6Address (org.onlab.packet.Ip6Address)10 Ip4Address (org.onlab.packet.Ip4Address)7 Test (org.junit.Test)6 MacAddress (org.onlab.packet.MacAddress)3 Lists (com.google.common.collect.Lists)2 Streams.stream (com.google.common.collect.Streams.stream)2 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 Collections (java.util.Collections)2 List (java.util.List)2 Optional (java.util.Optional)2 Set (java.util.Set)2 Collectors (java.util.stream.Collectors)2 IpAddress (org.onlab.packet.IpAddress)2 IpPrefix (org.onlab.packet.IpPrefix)2 ItemNotFoundException (org.onlab.util.ItemNotFoundException)2 ApplicationId (org.onosproject.core.ApplicationId)2 MastershipService (org.onosproject.mastership.MastershipService)2