Add Close loop mechanism to PCE Server
[bgpcep.git] / bgp / topology-provider / src / main / java / org / opendaylight / bgpcep / bgp / topology / provider / LinkstateGraphBuilder.java
index eee5fd630a6333951fd03b361bb6d8fb18ffd5e6..033ee8bd9b8d478c43559b318a7aadd3a47420c1 100644 (file)
@@ -11,22 +11,20 @@ import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.VisibleForTesting;
-import java.math.BigDecimal;
+import com.google.common.collect.ImmutableSet;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
 import org.opendaylight.graph.ConnectedGraph;
 import org.opendaylight.graph.ConnectedGraphProvider;
 import org.opendaylight.mdsal.binding.api.DataBroker;
+import org.opendaylight.mdsal.binding.api.DataObjectModification;
+import org.opendaylight.mdsal.binding.api.DataTreeModification;
 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
 import org.opendaylight.protocol.bgp.rib.RibReference;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv4InterfaceIdentifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv6InterfaceIdentifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateAddressFamily;
@@ -102,13 +100,12 @@ import org.slf4j.LoggerFactory;
  * @author Philippe Niger
  */
 public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRoute> {
+    private static final Logger LOG = LoggerFactory.getLogger(LinkstateGraphBuilder.class);
     private static final TopologyTypes LINKSTATE_TOPOLOGY_TYPE = new TopologyTypesBuilder().addAugmentation(
             new TopologyTypes1Builder().setBgpLinkstateTopology(new BgpLinkstateTopologyBuilder().build()).build())
             .build();
-
     private static final String UNHANDLED_OBJECT_CLASS = "Unhandled object class {}";
-
-    private static final Logger LOG = LoggerFactory.getLogger(LinkstateGraphBuilder.class);
+    private static final int MAX_PRIORITY = 8;
 
     private final ConnectedGraph cgraph;
 
@@ -116,11 +113,11 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
             final TopologyId topologyId, final ConnectedGraphProvider provider) {
         super(dataProvider, locRibReference, topologyId, LINKSTATE_TOPOLOGY_TYPE, LinkstateAddressFamily.class,
                 LinkstateSubsequentAddressFamily.class);
-        this.cgraph = requireNonNull(provider).createConnectedGraph("ted://" + topologyId.getValue(),
+        cgraph = requireNonNull(provider).createConnectedGraph("ted://" + topologyId.getValue(),
                 DomainScope.IntraDomain);
         /* LinkStateGraphBuilder doesn't write information in the Network Topology tree of the Data Store.
          * This is performed by ConnectedGraphProvider which write element in Graph tree of the Data Store */
-        this.networkTopologyTransaction = false;
+        networkTopologyTransaction = false;
         LOG.info("Started Traffic Engineering Graph Builder");
     }
 
@@ -130,14 +127,30 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
             final int listenerResetEnforceCounter) {
         super(dataProvider, locRibReference, topologyId, LINKSTATE_TOPOLOGY_TYPE, LinkstateAddressFamily.class,
                 LinkstateSubsequentAddressFamily.class, listenerResetLimitInMillsec, listenerResetEnforceCounter);
-        this.cgraph = requireNonNull(provider).createConnectedGraph("ted://" + topologyId.getValue(),
+        cgraph = requireNonNull(provider).createConnectedGraph("ted://" + topologyId.getValue(),
                 DomainScope.IntraDomain);
         /* LinkStateGraphBuilder doesn't write information in the Network Topology tree of the Data Store.
          * This is performed by ConnectedGraphProvider which write element in Graph tree of the Data Store */
-        this.networkTopologyTransaction = false;
+        networkTopologyTransaction = false;
         LOG.info("Started Traffic Engineering Graph Builder");
     }
 
+    @Override
+    protected void routeChanged(final DataTreeModification<LinkstateRoute> change, final ReadWriteTransaction trans) {
+        final DataObjectModification<LinkstateRoute> root = change.getRootNode();
+        switch (root.getModificationType()) {
+            case DELETE:
+                removeObject(trans, change.getRootPath().getRootIdentifier(), root.getDataBefore());
+                break;
+            case SUBTREE_MODIFIED:
+            case WRITE:
+                createObject(trans, change.getRootPath().getRootIdentifier(), root.getDataAfter());
+                break;
+            default:
+                throw new IllegalArgumentException("Unhandled modification type " + root.getModificationType());
+        }
+    }
+
     @Override
     protected void createObject(final ReadWriteTransaction trans, final InstanceIdentifier<LinkstateRoute> id,
             final LinkstateRoute value) {
@@ -183,19 +196,14 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
      * @return Link Attributes
      */
     private static LinkAttributes getLinkAttributes(final Attributes attributes) {
-        final LinkAttributes la;
         final Attributes1 attr = attributes.augmentation(Attributes1.class);
         if (attr != null) {
             final LinkStateAttribute attrType = attr.getLinkStateAttribute();
-            if (attrType != null) {
-                la = ((LinkAttributesCase) attrType).getLinkAttributes();
-            } else {
-                return null;
+            if (attrType instanceof LinkAttributesCase) {
+                return ((LinkAttributesCase) attrType).getLinkAttributes();
             }
-        } else {
-            return null;
         }
-        return la;
+        return null;
     }
 
     /**
@@ -260,14 +268,13 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
 
         /*
          * Add corresponding Prefix for the Local Address. Remote address will be added with the remote Edge */
+        final var localAddress = edge.getEdgeAttributes().getLocalAddress();
         PrefixBuilder prefBuilder = new PrefixBuilder().setVertexId(srcId);
-        if (edge.getEdgeAttributes().getLocalAddress().getIpv4Address() != null) {
-            prefBuilder.setPrefix(new IpPrefix(
-                    new Ipv4Prefix(edge.getEdgeAttributes().getLocalAddress().getIpv4Address().getValue() + "/32")));
+        if (localAddress.getIpv4Address() != null) {
+            prefBuilder.setPrefix(new IpPrefix(IetfInetUtil.INSTANCE.ipv4PrefixFor(localAddress.getIpv4Address())));
         }
-        if (edge.getEdgeAttributes().getLocalAddress().getIpv6Address() != null) {
-            prefBuilder.setPrefix(new IpPrefix(
-                    new Ipv6Prefix(edge.getEdgeAttributes().getLocalAddress().getIpv6Address().getValue() + "/128")));
+        if (localAddress.getIpv6Address() != null) {
+            prefBuilder.setPrefix(new IpPrefix(IetfInetUtil.INSTANCE.ipv6PrefixFor(localAddress.getIpv6Address())));
         }
         Prefix prefix = prefBuilder.build();
 
@@ -277,8 +284,6 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
         cgraph.addPrefix(prefix);
     }
 
-    private static final int MAX_PRIORITY = 8;
-
     /**
      * Create Edge Attributes from Link attributes.
      *
@@ -291,16 +296,16 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
         EdgeAttributesBuilder builder = new EdgeAttributesBuilder();
 
         if (linkDesc.getIpv4InterfaceAddress() != null) {
-            builder.setLocalAddress(new IpAddress(new Ipv4Address(linkDesc.getIpv4InterfaceAddress())));
+            builder.setLocalAddress(new IpAddress(linkDesc.getIpv4InterfaceAddress()));
         }
         if (linkDesc.getIpv6InterfaceAddress() != null) {
-            builder.setLocalAddress(new IpAddress(new Ipv6Address(linkDesc.getIpv6InterfaceAddress())));
+            builder.setLocalAddress(new IpAddress(linkDesc.getIpv6InterfaceAddress()));
         }
         if (linkDesc.getIpv4NeighborAddress() != null) {
-            builder.setRemoteAddress(new IpAddress(new Ipv4Address(linkDesc.getIpv4NeighborAddress())));
+            builder.setRemoteAddress(new IpAddress(linkDesc.getIpv4NeighborAddress()));
         }
         if (linkDesc.getIpv6NeighborAddress() != null) {
-            builder.setRemoteAddress(new IpAddress(new Ipv6Address(linkDesc.getIpv6NeighborAddress())));
+            builder.setRemoteAddress(new IpAddress(linkDesc.getIpv6NeighborAddress()));
         }
         if (linkDesc.getLinkLocalIdentifier() != null) {
             builder.setLocalIdentifier(linkDesc.getLinkLocalIdentifier());
@@ -360,11 +365,11 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
             builder.setUtilizedBandwidth(bandwithToDecimalBandwidth(la.getUtilizedBandwidth()));
         }
         if (la.getSharedRiskLinkGroups() != null) {
-            List<Uint32> srlgs = new ArrayList<>();
+            final var srlgs = ImmutableSet.<Uint32>builder();
             for (SrlgId srlg : la.getSharedRiskLinkGroups()) {
                 srlgs.add(srlg.getValue());
             }
-            builder.setSrlgs(srlgs);
+            builder.setSrlgs(srlgs.build());
         }
         for (SrAdjIds adj : la.nonnullSrAdjIds()) {
             if (adj.getSidLabelIndex() instanceof LocalLabelCase) {
@@ -515,7 +520,7 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
         final Attributes1 attr = attributes.augmentation(Attributes1.class);
         if (attr != null) {
             final LinkStateAttribute attrType = attr.getLinkStateAttribute();
-            if (attrType != null) {
+            if (attrType instanceof PrefixAttributesCase) {
                 pa = ((PrefixAttributesCase) attrType).getPrefixAttributes();
             } else {
                 LOG.warn("Missing attribute type in IP {} prefix {} route {}, skipping it", ippfx, prefixCase, value);
@@ -538,7 +543,7 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
         }
 
         /* Create Prefix */
-        PrefixBuilder builder = new PrefixBuilder().setVertexId(vertexId);
+        PrefixBuilder builder = new PrefixBuilder().setVertexId(vertexId).setPrefix(ippfx);
         if (pa.getSrPrefix() != null && pa.getSrPrefix().getSidLabelIndex() instanceof SidCase) {
             builder.setPrefixSid(((SidCase) pa.getSrPrefix().getSidLabelIndex()).getSid());
             if (pa.getSrPrefix().getFlags() instanceof IsisPrefixFlagsCase) {
@@ -552,12 +557,6 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
                 builder.setNodeSid(true);
             }
         }
-        if (ippfx.getIpv4Prefix() != null) {
-            builder.setPrefix(new IpPrefix(ippfx.getIpv4Prefix()));
-        }
-        if (ippfx.getIpv6Prefix() != null) {
-            builder.setPrefix(new IpPrefix(ippfx.getIpv6Prefix()));
-        }
         Prefix prefix = builder.build();
 
         /* Add the Prefix to the Connected Vertex within the Connected Graph */
@@ -647,18 +646,18 @@ public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRout
     }
 
     private static DecimalBandwidth bandwithToDecimalBandwidth(final Bandwidth bw) {
-        return new DecimalBandwidth(BigDecimal.valueOf(ByteBuffer.wrap(bw.getValue()).getFloat()));
+        return new DecimalBandwidth(ProtocolUtil.bandwidthToDecimal64(bw));
     }
 
     private static Uint64 ipv4ToKey(final Ipv4InterfaceIdentifier ifId) {
         return Uint32.fromIntBits(IetfInetUtil.INSTANCE.ipv4AddressNoZoneBits(ifId)).toUint64();
     }
 
-    private static Uint64 ipv6ToKey(final Ipv6InterfaceIdentifier ifId) {
+    @VisibleForTesting
+    static Uint64 ipv6ToKey(final Ipv6InterfaceIdentifier ifId) {
         final byte[] ip = IetfInetUtil.INSTANCE.ipv6AddressNoZoneBytes(ifId);
-        /* Keep only the lower 64bits from the IP address */
-        final byte[] key = {ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]};
-        return Uint64.fromLongBits(ByteBuffer.wrap(key).getLong());
+        // Keep only the lower 64bits from the IP address, i.e. we skip first Long.BYTES bytes
+        return Uint64.fromLongBits(ByteBuffer.wrap(ip, Long.BYTES, Long.BYTES).getLong());
     }
 
     @Override