BUG 5031:
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / impl / nlri / LinkstateNlriParser.java
similarity index 68%
rename from bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/nlri/LinkstateNlriParser.java
rename to bgp/linkstate/src/main/java/org/opendaylight/protocol/bgp/linkstate/impl/nlri/LinkstateNlriParser.java
index 8281d91406ca600bdd947ddd505161b6ea58e5ee..0b89a0d23dede07607c2c9315b86f97ba4e291f5 100644 (file)
@@ -5,22 +5,21 @@
  * 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.linkstate.nlri;
+package org.opendaylight.protocol.bgp.linkstate.impl.nlri;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
-import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
+import org.opendaylight.protocol.bgp.linkstate.spi.AbstractTeLspNlriCodec;
+import org.opendaylight.protocol.bgp.linkstate.spi.pojo.SimpleNlriTypeRegistry;
 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.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.Identifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NlriType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ProtocolId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.RouteDistinguisher;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.ObjectType;
@@ -42,10 +41,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess
 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.WithdrawnRoutes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -63,18 +62,6 @@ import org.slf4j.LoggerFactory;
  */
 public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
 
-    private static final Logger LOG = LoggerFactory.getLogger(LinkstateNlriParser.class);
-
-    private static final int ROUTE_DISTINGUISHER_LENGTH = 8;
-    private static final int PROTOCOL_ID_LENGTH = 1;
-    private static final int IDENTIFIER_LENGTH = 8;
-
-    private static final int TYPE_LENGTH = 2;
-    private static final int LENGTH_SIZE = 2;
-
-    private static final int LOCAL_NODE_DESCRIPTORS_TYPE = 256;
-    private static final int REMOTE_NODE_DESCRIPTORS_TYPE = 257;
-
     @VisibleForTesting
     public static final NodeIdentifier OBJECT_TYPE_NID = new NodeIdentifier(ObjectType.QNAME);
     @VisibleForTesting
@@ -89,67 +76,30 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
     public static final NodeIdentifier PREFIX_DESCRIPTORS_NID = new NodeIdentifier(PrefixDescriptors.QNAME);
     @VisibleForTesting
     public static final NodeIdentifier LINK_DESCRIPTORS_NID = new NodeIdentifier(LinkDescriptors.QNAME);
-
-    @VisibleForTesting
-    public static final NodeIdentifier DISTINGUISHER_NID = new NodeIdentifier(QName.create(CLinkstateDestination.QNAME, "distinguisher").intern());
     @VisibleForTesting
     public static final NodeIdentifier PROTOCOL_ID_NID = new NodeIdentifier(QName.create(CLinkstateDestination.QNAME, "protocol-id").intern());
     @VisibleForTesting
     public static final NodeIdentifier IDENTIFIER_NID = new NodeIdentifier(QName.create(CLinkstateDestination.QNAME, "identifier").intern());
-
-    private final boolean isVpn;
-
-    public LinkstateNlriParser(final boolean isVpn) {
-        this.isVpn = isVpn;
-    }
+    private static final Logger LOG = LoggerFactory.getLogger(LinkstateNlriParser.class);
+    @VisibleForTesting
+    private static final NodeIdentifier DISTINGUISHER_NID = new NodeIdentifier(QName.create(CLinkstateDestination.QNAME, "distinguisher").intern());
+    private final SimpleNlriTypeRegistry nlriTypeReg = SimpleNlriTypeRegistry.getInstance();
 
 
     /**
      * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
      *
      * @param nlri as byte array
-     * @param isVpn flag which determines that destination has route distinguisher
      * @return {@link CLinkstateDestination}
-     * @throws BGPParsingException if parsing was unsuccessful
      */
-    public static List<CLinkstateDestination> parseNlri(final ByteBuf nlri, final boolean isVpn) throws BGPParsingException {
+    private List<CLinkstateDestination> parseNlri(final ByteBuf nlri) {
         final List<CLinkstateDestination> dests = new ArrayList<>();
         while (nlri.isReadable()) {
-            final CLinkstateDestinationBuilder builder = new CLinkstateDestinationBuilder();
-            final NlriType type = NlriType.forValue(nlri.readUnsignedShort());
-
-            // length means total length of the tlvs including route distinguisher not including the type field
-            final int length = nlri.readUnsignedShort();
-            RouteDistinguisher distinguisher = null;
-            if (isVpn) {
-                // this parses route distinguisher
-                distinguisher = new RouteDistinguisher(BigInteger.valueOf(nlri.readLong()));
-                builder.setDistinguisher(distinguisher);
-            }
-            // parse source protocol
-            final ProtocolId sp = ProtocolId.forValue(nlri.readByte());
-            builder.setProtocolId(sp);
-
-            // parse identifier
-            final Identifier identifier = new Identifier(BigInteger.valueOf(nlri.readLong()));
-            builder.setIdentifier(identifier);
-
-            // if we are dealing with linkstate nodes/links, parse local node descriptor
-            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NodeIdentifier localDescriptor = null;
-            ByteBuf rest = null;
-            if (!type.equals(NlriType.Ipv4TeLsp) && !type.equals(NlriType.Ipv6TeLsp)) {
-                final int localtype = nlri.readUnsignedShort();
-                final int locallength = nlri.readUnsignedShort();
-                if (localtype == LOCAL_NODE_DESCRIPTORS_TYPE) {
-                    localDescriptor = NodeNlriParser.parseNodeDescriptors(nlri.readSlice(locallength), type, true);
-                }
-                final int restLength = length - (isVpn ? ROUTE_DISTINGUISHER_LENGTH : 0) - PROTOCOL_ID_LENGTH -
-                    IDENTIFIER_LENGTH - TYPE_LENGTH - LENGTH_SIZE - locallength;
-                LOG.trace("Restlength {}", restLength);
-                rest = nlri.readSlice(restLength);
+            final CLinkstateDestination destination = this.nlriTypeReg.parseNlriType(nlri);
+            if (destination == null) {
+                continue;
             }
-            builder.setObjectType(SimpleNlriTypeRegistry.getInstance().parseNlriType(nlri, type, localDescriptor, rest));
-            dests.add(builder.build());
+            dests.add(destination);
         }
         return dests;
     }
@@ -159,7 +109,7 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
         if (!nlri.isReadable()) {
             return;
         }
-        final List<CLinkstateDestination> dst = parseNlri(nlri, this.isVpn);
+        final List<CLinkstateDestination> dst = parseNlri(nlri);
 
         builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCaseBuilder().setDestinationLinkstate(
@@ -172,32 +122,13 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
         if (!nlri.isReadable()) {
             return;
         }
-        final List<CLinkstateDestination> dst = parseNlri(nlri, this.isVpn);
+        final List<CLinkstateDestination> dst = parseNlri(nlri);
 
         builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
             new DestinationLinkstateCaseBuilder().setDestinationLinkstate(
                 new DestinationLinkstateBuilder().setCLinkstateDestination(dst).build()).build()).build());
     }
 
-    /**
-     * Serializes Linkstate NLRI to byte array. We need this as NLRI serves as a key in upper layers.
-     *
-     * @param destination Linkstate NLRI to be serialized
-     * @param buffer where Linkstate NLRI will be serialized
-     */
-    public static void serializeNlri(final CLinkstateDestination destination, final ByteBuf buffer) {
-        final ByteBuf nlriByteBuf = Unpooled.buffer();
-        if (destination.getDistinguisher() != null) {
-            nlriByteBuf.writeBytes(destination.getDistinguisher().getValue().toByteArray());
-        }
-        nlriByteBuf.writeByte(destination.getProtocolId().getIntValue());
-        nlriByteBuf.writeLong(destination.getIdentifier().getValue().longValue());
-        final ByteBuf ldescs = Unpooled.buffer();
-        final NlriType nlriType = SimpleNlriTypeRegistry.getInstance().serializeNlriType(destination, ldescs, nlriByteBuf);
-        Preconditions.checkNotNull(nlriType, "NLRI Type value should not be null.");
-        TlvUtil.writeTLV(nlriType.getIntValue(), nlriByteBuf, buffer);
-    }
-
     @Override
     public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
         Preconditions.checkArgument(attribute instanceof Attributes, "Attribute parameter is not a PathAttribute object.");
@@ -205,25 +136,30 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
         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.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) {
-                final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase
-                    linkstateCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) routes.getDestinationType();
+            serializeAdvertisedRoutes((pathAttributes1.getMpReachNlri()).getAdvertizedRoutes(), byteAggregator);
+        } else if (pathAttributes2 != null) {
+            serializeWithDrawnRoutes(pathAttributes2.getMpUnreachNlri().getWithdrawnRoutes(), byteAggregator);
+        }
+    }
 
-                for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
-                    serializeNlri(cLinkstateDestination, byteAggregator);
-                }
+    private void serializeWithDrawnRoutes(final WithdrawnRoutes withdrawnRoutes, final ByteBuf byteAggregator) {
+        if (withdrawnRoutes != null && withdrawnRoutes.getDestinationType() instanceof DestinationLinkstateCase) {
+            final DestinationLinkstateCase linkstateCase = (DestinationLinkstateCase) withdrawnRoutes.getDestinationType();
+            for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
+                this.nlriTypeReg.serializeNlriType(cLinkstateDestination, byteAggregator);
             }
-        } else if (pathAttributes2 != null) {
-            final MpUnreachNlri mpUnreachNlri = pathAttributes2.getMpUnreachNlri();
-            if (mpUnreachNlri.getWithdrawnRoutes() != null && mpUnreachNlri.getWithdrawnRoutes().getDestinationType() instanceof DestinationLinkstateCase) {
-                final DestinationLinkstateCase linkstateCase = (DestinationLinkstateCase) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
-                for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
-                    serializeNlri(cLinkstateDestination, byteAggregator);
-                }
+        }
+    }
+
+    private void serializeAdvertisedRoutes(final AdvertizedRoutes advertizedRoutes, final ByteBuf byteAggregator) {
+        if (advertizedRoutes != null && advertizedRoutes.getDestinationType()
+            instanceof
+            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) {
+            final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase
+                linkstateCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) advertizedRoutes.getDestinationType();
+
+            for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
+                this.nlriTypeReg.serializeNlriType(cLinkstateDestination, byteAggregator);
             }
         }
     }
@@ -265,8 +201,8 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
             serializeLocalNodeDescriptor(builder, objectType);
         } else if (objectType.getChild(NODE_DESCRIPTORS_NID).isPresent()) {
             serializeNodeDescriptor(builder, objectType);
-        } else if (TeLspNlriSerializer.isTeLsp(objectType)) {
-            builder.setObjectType(TeLspNlriSerializer.serializeTeLsp(objectType));
+        } else if (AbstractTeLspNlriCodec.isTeLsp(objectType)) {
+            builder.setObjectType(AbstractTeLspNlriCodec.serializeTeLsp(objectType));
         } else {
             LOG.warn("Unknown Object Type: {}.", objectType);
         }
@@ -306,7 +242,7 @@ public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
         // prefix descriptors
         final Optional<DataContainerChild<? extends PathArgument, ?>> prefixDescriptors = objectType.getChild(PREFIX_DESCRIPTORS_NID);
         if (prefixDescriptors.isPresent()) {
-            prefixBuilder.setPrefixDescriptors(PrefixNlriSerializer.serializePrefixDescriptors((ContainerNode) prefixDescriptors.get()));
+            prefixBuilder.setPrefixDescriptors(AbstractPrefixNlriParser.serializePrefixDescriptors((ContainerNode) prefixDescriptors.get()));
         }
         builder.setObjectType(prefixBuilder.build());
     }