implemented VPN IPv4 Nlri and NextHop handler.
created BGPActivater and registered handlers.
Implemented unit tests.
ref.: https://tools.ietf.org/html/rfc4364#section-4.3
Change-Id: I6e8943ec78e7010792e37ad4c39e911025e13416
Signed-off-by: Iveta Halanova <ihalanov@cisco.com>
private static final int IPV4_TYPE = 1;
private static final int AS_4BYTE_TYPE = 2;
private static final char SEPARATOR = ':';
+ public static final int RD_LENGTH = 8;
private RouteDistinguisherUtil() {
throw new UnsupportedOperationException();
<groupId>${project.groupId}</groupId>
<artifactId>bgp-labeled-unicast</artifactId>
</dependency>
+
+ <!-- test scope dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
</dependencies>
<build>
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.l3vpn;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.protocol.bgp.parser.spi.AbstractBGPExtensionProviderActivator;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.vpn.ipv4.routes.VpnIpv4Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.MplsLabeledVpnSubsequentAddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.Ipv4NextHopCase;
+
+public final class BGPActivator extends AbstractBGPExtensionProviderActivator {
+
+ @Override
+ protected List<AutoCloseable> startImpl(final BGPExtensionProviderContext context) {
+ final List<AutoCloseable> regs = new ArrayList<>();
+
+ final VpnIpv4NlriParser nlriParser = new VpnIpv4NlriParser();
+ final VpnIpv4NextHopParserSerializer nextHopParser = new VpnIpv4NextHopParserSerializer();
+
+ regs.add(context.registerNlriParser(Ipv4AddressFamily.class, MplsLabeledVpnSubsequentAddressFamily.class,
+ nlriParser, nextHopParser, Ipv4NextHopCase.class));
+ regs.add(context.registerNlriSerializer(VpnIpv4Routes.class, nlriParser));
+
+ return regs;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.l3vpn;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import org.opendaylight.bgp.concepts.NextHopUtil;
+import org.opendaylight.bgp.concepts.RouteDistinguisherUtil;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.spi.NextHopParserSerializer;
+import org.opendaylight.protocol.util.Ipv4Util;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.CNextHop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.Ipv4NextHopCase;
+
+public final class VpnIpv4NextHopParserSerializer implements NextHopParserSerializer {
+
+ @Override
+ public CNextHop parseNextHop(final ByteBuf buffer) throws BGPParsingException {
+ Preconditions.checkArgument(buffer.readableBytes() == (Ipv4Util.IP4_LENGTH + RouteDistinguisherUtil.RD_LENGTH), "Length of byte array for NEXT_HOP should be %s, but is %s", Ipv4Util.IP4_LENGTH + RouteDistinguisherUtil.RD_LENGTH, buffer.readableBytes());
+ buffer.readBytes(RouteDistinguisherUtil.RD_LENGTH);
+ return NextHopUtil.parseNextHop(buffer.readBytes(Ipv4Util.IP4_LENGTH));
+ }
+
+ @Override
+ public void serializeNextHop(final CNextHop cNextHop, final ByteBuf byteAggregator) {
+ Preconditions.checkArgument(cNextHop instanceof Ipv4NextHopCase, "cNextHop is not a VPN Ipv4 NextHop object.");
+ byteAggregator.writeZero(RouteDistinguisherUtil.RD_LENGTH);
+ NextHopUtil.serializeNextHop(cNextHop, byteAggregator);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.l3vpn;
+
+import com.google.common.base.Preconditions;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.bgp.concepts.RouteDistinguisherUtil;
+import org.opendaylight.protocol.bgp.labeled.unicast.LUNlriParser;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
+import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationVpnIpv4CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.vpn.ipv4._case.DestinationVpnIpv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationVpnIpv4Case;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.vpn.ipv4.destination.VpnIpv4Destination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.vpn.ipv4.destination.VpnIpv4DestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.labeled.unicast.LabelStack;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public class VpnIpv4NlriParser implements NlriParser, NlriSerializer {
+
+ @Override
+ public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
+ Preconditions.checkArgument(attribute instanceof Attributes, "Attribute parameter is not a Attributes object");
+ final Attributes pathAttributes = (Attributes) attribute;
+ final Attributes1 pathAttributes1 = pathAttributes.getAugmentation(Attributes1.class);
+ final Attributes2 pathAttributes2 = pathAttributes.getAugmentation(Attributes2.class);
+ if (pathAttributes1 != null) {
+ final AdvertizedRoutes routes = (pathAttributes1.getMpReachNlri()).getAdvertizedRoutes();
+ if ((routes != null) && (routes.getDestinationType() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationVpnIpv4Case)) {
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationVpnIpv4Case labeledUnicastCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationVpnIpv4Case) routes.getDestinationType();
+ serializeNlri(labeledUnicastCase.getDestinationVpnIpv4().getVpnIpv4Destination(), byteAggregator);
+ }
+ } else if (pathAttributes2 != null) {
+ final MpUnreachNlri mpUnreachNlri = pathAttributes2.getMpUnreachNlri();
+ if ((mpUnreachNlri.getWithdrawnRoutes() != null) && (mpUnreachNlri.getWithdrawnRoutes().getDestinationType() instanceof DestinationVpnIpv4Case)) {
+ final DestinationVpnIpv4Case labeledUnicastCase = (DestinationVpnIpv4Case) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
+ serializeNlri(labeledUnicastCase.getDestinationVpnIpv4().getVpnIpv4Destination(), byteAggregator);
+ }
+ }
+ }
+
+ protected static void serializeNlri(final List<VpnIpv4Destination> dests, final ByteBuf buffer) {
+ final ByteBuf nlriByteBuf = Unpooled.buffer();
+ for (final VpnIpv4Destination dest: dests) {
+ final List<LabelStack> labelStack = dest.getLabelStack();
+ final IpPrefix prefix = dest.getPrefix();
+ // Serialize the length field
+ // Length field contains one Byte which represents the length of label stack and prefix in bits
+ nlriByteBuf.writeByte(((LUNlriParser.LABEL_LENGTH * labelStack.size()) + LUNlriParser.getPrefixLength(prefix) + RouteDistinguisherUtil.RD_LENGTH) * Byte.SIZE);
+
+ LUNlriParser.serializeLabelStackEntries(labelStack, nlriByteBuf);
+ RouteDistinguisherUtil.serializeRouteDistinquisher(dest.getRouteDistinguisher(), nlriByteBuf);
+ Preconditions.checkNotNull(prefix.getIpv4Prefix(), "Ipv4 prefix is missing.");
+ LUNlriParser.serializePrefixField(prefix, nlriByteBuf);
+ }
+ buffer.writeBytes(nlriByteBuf);
+ }
+
+ @Override
+ public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
+ if (!nlri.isReadable()) {
+ return;
+ }
+ final List<VpnIpv4Destination> dst = parseNlri(nlri, builder.getAfi());
+
+ builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationVpnIpv4CaseBuilder().setDestinationVpnIpv4(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.vpn.ipv4._case.DestinationVpnIpv4Builder().setVpnIpv4Destination(
+ dst).build()).build()).build());
+ }
+
+ @Override
+ public void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder) throws BGPParsingException {
+ if (!nlri.isReadable()) {
+ return;
+ }
+ final List<VpnIpv4Destination> dst = parseNlri(nlri, builder.getAfi());
+
+ builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
+ new DestinationVpnIpv4CaseBuilder().setDestinationVpnIpv4(
+ new DestinationVpnIpv4Builder().setVpnIpv4Destination(
+ dst).build()).build()).build());
+ }
+
+ private static List<VpnIpv4Destination> parseNlri(final ByteBuf nlri, final Class<? extends AddressFamily> afi) {
+ if (!nlri.isReadable()) {
+ return null;
+ }
+ final List<VpnIpv4Destination> dests = new ArrayList<>();
+
+ while (nlri.isReadable()) {
+ final VpnIpv4DestinationBuilder builder = new VpnIpv4DestinationBuilder();
+ final short length = nlri.readUnsignedByte();
+ builder.setLabelStack(LUNlriParser.parseLabel(nlri));
+ final int labelNum = builder.getLabelStack().size();
+ final int prefixLen = length - (LUNlriParser.LABEL_LENGTH * Byte.SIZE * labelNum) - (RouteDistinguisherUtil.RD_LENGTH * Byte.SIZE);
+ builder.setRouteDistinguisher(RouteDistinguisherUtil.parseRouteDistinguisher(nlri));
+ Preconditions.checkState(prefixLen > 0, "VPN IPv4 is required.");
+ builder.setPrefix(LUNlriParser.parseIpPrefix(nlri, prefixLen, afi));
+ dests.add(builder.build());
+ }
+ return dests;
+ }
+
+}
}
grouping vpn-ipv4-destination {
- list c-vpn-ipv4-destination {
+ list vpn-ipv4-destination {
uses vpn-ipv4;
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.l3vpn;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+import org.opendaylight.protocol.bgp.parser.spi.pojo.SimpleBGPExtensionProviderContext;
+
+public class BGPActivatorTest {
+
+ @Test
+ public void testActivator() throws Exception {
+ final BGPActivator act = new BGPActivator();
+ final BGPExtensionProviderContext context = new SimpleBGPExtensionProviderContext();
+ assertFalse(context.getNlriRegistry().getSerializers().iterator().hasNext());
+ act.start(context);
+ assertTrue(context.getNlriRegistry().getSerializers().iterator().next() instanceof VpnIpv4NlriParser);
+ act.close();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.l3vpn;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.CNextHop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.Ipv4NextHopCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.Ipv4NextHopCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.ipv4.next.hop._case.Ipv4NextHopBuilder;
+
+public class VpnIpv4NextHopTest {
+
+ private static final VpnIpv4NextHopParserSerializer HANDLER = new VpnIpv4NextHopParserSerializer();
+
+ @Test
+ public void testSerializeIpv4NextHopCase() throws BGPParsingException {
+ final ByteBuf buffer = Unpooled.buffer();
+ final byte[] nextHop = {0, 0, 0, 0, 0, 0, 0, 0, 42, 42, 42, 42};
+ final CNextHop hop = new Ipv4NextHopCaseBuilder().setIpv4NextHop(new Ipv4NextHopBuilder()
+ .setGlobal(new Ipv4Address("42.42.42.42")).build()).build();
+
+ HANDLER.serializeNextHop(hop, buffer);
+ assertArrayEquals(nextHop, ByteArray.readAllBytes(buffer));
+
+ final CNextHop parsedHop = HANDLER.parseNextHop(Unpooled.wrappedBuffer(nextHop));
+ assertTrue(hop instanceof Ipv4NextHopCase);
+ assertEquals(hop, parsedHop);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.protocol.bgp.l3vpn;
+
+import com.google.common.collect.Lists;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import java.util.List;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.protocol.bgp.parser.BGPParsingException;
+import org.opendaylight.protocol.util.ByteArray;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationVpnIpv4CaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.vpn.ipv4._case.DestinationVpnIpv4Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.vpn.ipv4.destination.VpnIpv4Destination;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.vpn.ipv4.destination.VpnIpv4DestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.labeled.unicast.LabelStack;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.labeled.unicast.LabelStackBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AttributesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.RouteDistinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
+
+
+public class VpnIpv4NlriParserTest {
+
+ private static final VpnIpv4NlriParser PARSER = new VpnIpv4NlriParser();
+
+ private static final byte[] NLRI_TYPE1 = new byte[] {
+ (byte) 0x70,
+ (byte) 0x00, (byte) 0x16, (byte) 0x31,
+ 0, 1, 1, 2, 3, 4, 1, 2,
+ (byte) 0x22, (byte) 0x01, (byte) 0x16,
+ };
+ private static final IpPrefix IPv4_PREFIX = new IpPrefix(new Ipv4Prefix("34.1.22.0/24"));
+ private static final List<LabelStack> LABEL_STACK = Lists.newArrayList(
+ new LabelStackBuilder().setLabelValue(new MplsLabel(355L)).build());
+ private static final RouteDistinguisher DISTINGUISHER = new RouteDistinguisher("1.2.3.4:258");
+ private static final VpnIpv4Destination VPN = new VpnIpv4DestinationBuilder().setRouteDistinguisher(DISTINGUISHER).setPrefix(IPv4_PREFIX).setLabelStack(LABEL_STACK).build();
+
+ @Test
+ public void testMpReachNlri() throws BGPParsingException {
+ final MpReachNlriBuilder mpBuilder = new MpReachNlriBuilder();
+ mpBuilder.setAfi(Ipv4AddressFamily.class);
+ mpBuilder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
+ new DestinationVpnIpv4CaseBuilder().setDestinationVpnIpv4(
+ new DestinationVpnIpv4Builder().setVpnIpv4Destination(Lists.newArrayList(VPN)).build()).build()).build());
+
+ final MpReachNlri mpReachExpected = mpBuilder.build();
+
+ final MpReachNlriBuilder testBuilder = new MpReachNlriBuilder();
+ testBuilder.setAfi(Ipv4AddressFamily.class);
+ PARSER.parseNlri(Unpooled.copiedBuffer(NLRI_TYPE1), testBuilder);
+ Assert.assertEquals(mpReachExpected, testBuilder.build());
+
+ final ByteBuf output = Unpooled.buffer();
+ PARSER.serializeAttribute(new AttributesBuilder().addAugmentation(Attributes1.class,
+ new Attributes1Builder().setMpReachNlri(mpReachExpected).build()).build(), output);
+ Assert.assertArrayEquals(NLRI_TYPE1, ByteArray.readAllBytes(output));
+ }
+
+ @Test
+ public void testMpUnreachNlri() throws BGPParsingException {
+ final MpUnreachNlriBuilder mpBuilder = new MpUnreachNlriBuilder();
+ mpBuilder.setAfi(Ipv4AddressFamily.class);
+ mpBuilder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationVpnIpv4CaseBuilder().setDestinationVpnIpv4(
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.bgp.vpn.ipv4.rev160210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.vpn.ipv4._case.DestinationVpnIpv4Builder().setVpnIpv4Destination(Lists.newArrayList(VPN)).build()).build()).build());
+
+ final MpUnreachNlri mpUnreachExpected = mpBuilder.build();
+
+ final MpUnreachNlriBuilder testBuilder = new MpUnreachNlriBuilder();
+ testBuilder.setAfi(Ipv4AddressFamily.class);
+ PARSER.parseNlri(Unpooled.copiedBuffer(NLRI_TYPE1), testBuilder);
+ Assert.assertEquals(mpUnreachExpected, testBuilder.build());
+
+ final ByteBuf output = Unpooled.buffer();
+ PARSER.serializeAttribute(new AttributesBuilder().addAugmentation(Attributes2.class,
+ new Attributes2Builder().setMpUnreachNlri(mpUnreachExpected).build()).build(), output);
+ Assert.assertArrayEquals(NLRI_TYPE1, ByteArray.readAllBytes(output));
+ }
+}
public class LUNlriParser implements NlriParser, NlriSerializer {
- private static final int LABEL_LENGTH = 3;
+ public static final int LABEL_LENGTH = 3;
@Override
public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
final Attributes2 pathAttributes2 = pathAttributes.getAugmentation(Attributes2.class);
if (pathAttributes1 != null) {
final AdvertizedRoutes routes = (pathAttributes1.getMpReachNlri()).getAdvertizedRoutes();
- if (routes != null && routes.getDestinationType() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLabeledUnicastCase) {
+ if ((routes != null) && (routes.getDestinationType() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLabeledUnicastCase)) {
final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLabeledUnicastCase labeledUnicastCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev150525.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLabeledUnicastCase) routes.getDestinationType();
serializeNlri(labeledUnicastCase.getDestinationLabeledUnicast().getCLabeledUnicastDestination(), byteAggregator);
}
} else if (pathAttributes2 != null) {
final MpUnreachNlri mpUnreachNlri = pathAttributes2.getMpUnreachNlri();
- if (mpUnreachNlri.getWithdrawnRoutes() != null && mpUnreachNlri.getWithdrawnRoutes().getDestinationType() instanceof DestinationLabeledUnicastCase) {
+ if ((mpUnreachNlri.getWithdrawnRoutes() != null) && (mpUnreachNlri.getWithdrawnRoutes().getDestinationType() instanceof DestinationLabeledUnicastCase)) {
final DestinationLabeledUnicastCase labeledUnicastCase = (DestinationLabeledUnicastCase) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
serializeNlri(labeledUnicastCase.getDestinationLabeledUnicast().getCLabeledUnicastDestination(), byteAggregator);
}
for (final CLabeledUnicastDestination dest: dests) {
final List<LabelStack> labelStack = dest.getLabelStack();
final IpPrefix prefix = dest.getPrefix();
- final int stackSize = labelStack.size();
// Serialize the length field
// Length field contains one Byte which represents the length of label stack and prefix in bits
- nlriByteBuf.writeByte((LABEL_LENGTH * stackSize + getPrefixLength(prefix)) * Byte.SIZE);
-
- // Serialize the label stack entries
- int i = 1;
- for (final LabelStack labelStackEntry : labelStack) {
- if (i++ == stackSize) {
- //mark last label stack entry with bottom-bit
- nlriByteBuf.writeBytes(MplsLabelUtil.byteBufForMplsLabelWithBottomBit(labelStackEntry.getLabelValue()));
- } else {
- nlriByteBuf.writeBytes(MplsLabelUtil.byteBufForMplsLabel(labelStackEntry.getLabelValue()));
- }
- }
+ nlriByteBuf.writeByte(((LABEL_LENGTH * labelStack.size()) + getPrefixLength(prefix)) * Byte.SIZE);
- // Serialize the prefix field
- final byte[] prefixBytes = getPrefixBytes(prefix);
- nlriByteBuf.writeBytes(Arrays.copyOfRange(prefixBytes, 1, prefixBytes.length));
+ serializeLabelStackEntries(labelStack, nlriByteBuf);
+ serializePrefixField(prefix, nlriByteBuf);
}
buffer.writeBytes(nlriByteBuf);
}
- private static int getPrefixLength(final IpPrefix prefix) {
+ public static void serializeLabelStackEntries(final List<LabelStack> stack, final ByteBuf buffer) {
+ int i = 1;
+ for (final LabelStack labelStackEntry : stack) {
+ if (i++ == stack.size()) {
+ //mark last label stack entry with bottom-bit
+ buffer.writeBytes(MplsLabelUtil.byteBufForMplsLabelWithBottomBit(labelStackEntry.getLabelValue()));
+ } else {
+ buffer.writeBytes(MplsLabelUtil.byteBufForMplsLabel(labelStackEntry.getLabelValue()));
+ }
+ }
+ }
+
+ public static void serializePrefixField(final IpPrefix prefix, final ByteBuf buffer) {
+ final byte[] prefixBytes = getPrefixBytes(prefix);
+ buffer.writeBytes(Arrays.copyOfRange(prefixBytes, 1, prefixBytes.length));
+ }
+
+ public static int getPrefixLength(final IpPrefix prefix) {
if (prefix.getIpv4Prefix() != null) {
return Ipv4Util.getPrefixLengthBytes(prefix.getIpv4Prefix().getValue());
}
while (nlri.isReadable()) {
final CLabeledUnicastDestinationBuilder builder = new CLabeledUnicastDestinationBuilder();
final short length = nlri.readUnsignedByte();
-
builder.setLabelStack(parseLabel(nlri));
-
final int labelNum = builder.getLabelStack().size();
- final int prefixLen = length - LABEL_LENGTH * Byte.SIZE * labelNum;
- final int prefixLenInByte = prefixLen / Byte.SIZE + ((prefixLen % Byte.SIZE == 0) ? 0 : 1);
- if (afi.equals(Ipv4AddressFamily.class)) {
- builder.setPrefix(new IpPrefix(Ipv4Util.prefixForBytes(ByteArray.readBytes(nlri, prefixLenInByte), prefixLen)));
- } else if (afi.equals(Ipv6AddressFamily.class)) {
- builder.setPrefix(new IpPrefix(Ipv6Util.prefixForBytes(ByteArray.readBytes(nlri, prefixLenInByte), prefixLen)));
- }
+ final int prefixLen = length - (LABEL_LENGTH * Byte.SIZE * labelNum);
+ builder.setPrefix(parseIpPrefix(nlri, prefixLen, afi));
dests.add(builder.build());
}
return dests;
}
- private static List<LabelStack> parseLabel(final ByteBuf nlri) {
+ public static IpPrefix parseIpPrefix(final ByteBuf nlri, final int prefixLen, final Class<? extends AddressFamily> afi) {
+ final int prefixLenInByte = (prefixLen / Byte.SIZE) + (((prefixLen % Byte.SIZE) == 0) ? 0 : 1);
+ if (afi.equals(Ipv4AddressFamily.class)) {
+ return new IpPrefix(Ipv4Util.prefixForBytes(ByteArray.readBytes(nlri, prefixLenInByte), prefixLen));
+ } else if (afi.equals(Ipv6AddressFamily.class)) {
+ return new IpPrefix(Ipv6Util.prefixForBytes(ByteArray.readBytes(nlri, prefixLenInByte), prefixLen));
+ }
+ return null;
+ }
+
+ public static List<LabelStack> parseLabel(final ByteBuf nlri) {
if (!nlri.isReadable()) {
return null;
}