2 * Copyright (c) 2020 Orange. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.bgpcep.bgp.topology.provider;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.collect.ImmutableSet;
15 import java.nio.ByteBuffer;
16 import java.util.ArrayList;
17 import java.util.List;
18 import org.opendaylight.graph.ConnectedGraph;
19 import org.opendaylight.graph.ConnectedGraphProvider;
20 import org.opendaylight.mdsal.binding.api.DataBroker;
21 import org.opendaylight.mdsal.binding.api.DataObjectModification;
22 import org.opendaylight.mdsal.binding.api.DataTreeModification;
23 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
24 import org.opendaylight.protocol.bgp.rib.RibReference;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv4InterfaceIdentifier;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv6InterfaceIdentifier;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateAddressFamily;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateSubsequentAddressFamily;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.ObjectType;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.SrAdjIds;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.LinkCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.NodeCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.PrefixCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LinkDescriptors;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.LinkStateAttribute;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.LinkAttributesCase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.NodeAttributesCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.link.attributes._case.LinkAttributes;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributes;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributes;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.LinkstateRoutes;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRoute;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.linkstate.route.Attributes1;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.CRouterIdentifier;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.IsisNodeCase;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.OspfNodeCase;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.adj.flags.flags.IsisAdjFlagsCase;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.adj.flags.flags.OspfAdjFlagsCase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.prefix.sid.tlv.flags.IsisPrefixFlagsCase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.SidLabelIndex;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.LocalLabelCase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.SidCase;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.DecimalBandwidth;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.Delay;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.Loss;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.Vertex.VertexType;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.edge.EdgeAttributes;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.edge.EdgeAttributesBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.edge.attributes.MinMaxDelay;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.edge.attributes.MinMaxDelayBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.edge.attributes.UnreservedBandwidth;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.edge.attributes.UnreservedBandwidthBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.edge.attributes.UnreservedBandwidthKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.Graph.DomainScope;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.Edge;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.EdgeBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.EdgeKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.Prefix;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.PrefixBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.Vertex;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.VertexBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.graph.topology.graph.VertexKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.graph.rev220720.vertex.SrgbBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1Builder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.odl.bgp.topology.types.rev160524.bgp.linkstate.topology.type.BgpLinkstateTopologyBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.SrlgId;
84 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
85 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypes;
86 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.TopologyTypesBuilder;
87 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
88 import org.opendaylight.yangtools.yang.common.Uint32;
89 import org.opendaylight.yangtools.yang.common.Uint64;
90 import org.slf4j.Logger;
91 import org.slf4j.LoggerFactory;
94 * This Class build the Traffic Engineering Database as a Connected Graph
95 * suitable to be used latter by Path Computation algorithms to compute end to
98 * @author Olivier Dugeon
99 * @author Philippe Niger
101 public class LinkstateGraphBuilder extends AbstractTopologyBuilder<LinkstateRoute> {
102 private static final Logger LOG = LoggerFactory.getLogger(LinkstateGraphBuilder.class);
103 private static final TopologyTypes LINKSTATE_TOPOLOGY_TYPE = new TopologyTypesBuilder().addAugmentation(
104 new TopologyTypes1Builder().setBgpLinkstateTopology(new BgpLinkstateTopologyBuilder().build()).build())
106 private static final String UNHANDLED_OBJECT_CLASS = "Unhandled object class {}";
107 private static final int MAX_PRIORITY = 8;
109 private final ConnectedGraph cgraph;
111 public LinkstateGraphBuilder(final DataBroker dataProvider, final RibReference locRibReference,
112 final TopologyId topologyId, final ConnectedGraphProvider provider) {
113 super(dataProvider, locRibReference, topologyId, LINKSTATE_TOPOLOGY_TYPE, LinkstateAddressFamily.VALUE,
114 LinkstateSubsequentAddressFamily.VALUE);
115 cgraph = requireNonNull(provider).createConnectedGraph("ted://" + topologyId.getValue(),
116 DomainScope.IntraDomain);
117 /* LinkStateGraphBuilder doesn't write information in the Network Topology tree of the Data Store.
118 * This is performed by ConnectedGraphProvider which write element in Graph tree of the Data Store */
119 networkTopologyTransaction = false;
120 LOG.info("Started Traffic Engineering Graph Builder");
124 LinkstateGraphBuilder(final DataBroker dataProvider, final RibReference locRibReference,
125 final TopologyId topologyId, final ConnectedGraphProvider provider, final long listenerResetLimitInMillsec,
126 final int listenerResetEnforceCounter) {
127 super(dataProvider, locRibReference, topologyId, LINKSTATE_TOPOLOGY_TYPE, LinkstateAddressFamily.VALUE,
128 LinkstateSubsequentAddressFamily.VALUE, listenerResetLimitInMillsec, listenerResetEnforceCounter);
129 cgraph = requireNonNull(provider).createConnectedGraph("ted://" + topologyId.getValue(),
130 DomainScope.IntraDomain);
131 /* LinkStateGraphBuilder doesn't write information in the Network Topology tree of the Data Store.
132 * This is performed by ConnectedGraphProvider which write element in Graph tree of the Data Store */
133 networkTopologyTransaction = false;
134 LOG.info("Started Traffic Engineering Graph Builder");
138 protected void routeChanged(final DataTreeModification<LinkstateRoute> change, final ReadWriteTransaction trans) {
139 final DataObjectModification<LinkstateRoute> root = change.getRootNode();
140 switch (root.getModificationType()) {
142 removeObject(trans, change.getRootPath().getRootIdentifier(), root.getDataBefore());
144 case SUBTREE_MODIFIED:
146 createObject(trans, change.getRootPath().getRootIdentifier(), root.getDataAfter());
149 throw new IllegalArgumentException("Unhandled modification type " + root.getModificationType());
154 protected void createObject(final ReadWriteTransaction trans, final InstanceIdentifier<LinkstateRoute> id,
155 final LinkstateRoute value) {
156 final ObjectType t = value.getObjectType();
157 checkArgument(t != null, "Route %s value %s has null object type", id, value);
159 if (t instanceof LinkCase) {
160 createEdge(value, (LinkCase) t, value.getAttributes());
161 } else if (t instanceof NodeCase) {
162 createVertex(value, (NodeCase) t, value.getAttributes());
163 } else if (t instanceof PrefixCase) {
164 createPrefix(value, (PrefixCase) t, value.getAttributes());
166 LOG.debug(UNHANDLED_OBJECT_CLASS, t.implementedInterface());
171 * Verify that mandatory information (Local & Remote Node and Link
172 * descriptors) are present in the link.
174 * @param linkCase The Link part of the Linkstate route
176 * @return True if all information are present, false otherwise
178 private static boolean checkLinkState(final LinkCase linkCase) {
179 if (linkCase.getLocalNodeDescriptors() == null || linkCase.getRemoteNodeDescriptors() == null) {
180 LOG.warn("Missing Local or Remote Node descriptor in link {}, skipping it", linkCase);
183 if (linkCase.getLinkDescriptors() == null) {
184 LOG.warn("Missing Link descriptor in link {}, skipping it", linkCase);
191 * Get Link attributes from the Link State route.
193 * @param attributes Link State Route Attributes
195 * @return Link Attributes
197 private static LinkAttributes getLinkAttributes(final Attributes attributes) {
198 final Attributes1 attr = attributes.augmentation(Attributes1.class);
200 final LinkStateAttribute attrType = attr.getLinkStateAttribute();
201 if (attrType instanceof LinkAttributesCase) {
202 return ((LinkAttributesCase) attrType).getLinkAttributes();
209 * Determine the Source Edge Key from the link descriptor.
210 * There is several case: IPv4, IPv6 address or Unnumbered Interface.
211 * For Multi-Topology i.e. IPv4 + IPv6, Edge Key is build from IPv4 address.
213 * @param linkCase The Link part of the Linkstate route
217 private static Uint64 getEdgeId(final LinkCase linkCase) {
218 final LinkDescriptors linkDescriptors = linkCase.getLinkDescriptors();
219 if (linkDescriptors.getIpv4InterfaceAddress() != null) {
220 return ipv4ToKey(linkDescriptors.getIpv4InterfaceAddress());
222 if (linkDescriptors.getIpv6InterfaceAddress() != null) {
223 return ipv6ToKey(linkDescriptors.getIpv6InterfaceAddress());
225 if (linkDescriptors.getLinkLocalIdentifier() != null) {
226 return linkDescriptors.getLinkLocalIdentifier().toUint64();
232 * Create new Connected Edge in the Connected Graph.
234 * @param value The complete Linkstate route information
235 * @param linkCase The Link part of the Linkstate route
236 * @param attributes The Link attributes
239 private void createEdge(final LinkstateRoute value, final LinkCase linkCase, final Attributes attributes) {
240 checkArgument(checkLinkState(linkCase), "Missing mandatory information in link {}", linkCase);
242 final LinkAttributes la = getLinkAttributes(attributes);
244 LOG.warn("Missing attributes in link {} route {}, skipping it", linkCase, value);
248 /* Get Source and Destination Vertex from the graph */
249 Uint64 srcId = getVertexId(linkCase.getLocalNodeDescriptors().getCRouterIdentifier());
250 Uint64 dstId = getVertexId(linkCase.getRemoteNodeDescriptors().getCRouterIdentifier());
251 if (srcId == Uint64.ZERO || dstId == Uint64.ZERO) {
252 LOG.warn("Unable to get the Source or Destination Vertex Identifier from link {}, skipping it", linkCase);
256 /* Get Source and Destination Key for the corresponding Edge */
257 Uint64 edgeId = getEdgeId(linkCase);
258 if (edgeId == Uint64.ZERO) {
259 LOG.warn("Unable to get the Edge Identifier from link {}, skipping it", linkCase);
263 /* Add associated Edge */
264 Edge edge = new EdgeBuilder().setEdgeId(edgeId).setLocalVertexId(srcId).setRemoteVertexId(dstId)
265 .setName(srcId + " - " + dstId)
266 .setEdgeAttributes(createEdgeAttributes(la, linkCase.getLinkDescriptors())).build();
269 * Add corresponding Prefix for the Local Address. Remote address will be added with the remote Edge */
270 final var attr = edge.getEdgeAttributes();
271 PrefixBuilder prefBuilder = new PrefixBuilder().setVertexId(srcId);
272 if (attr.getLocalAddress() != null) {
273 prefBuilder.setPrefix(new IpPrefix(IetfInetUtil.INSTANCE.ipv4PrefixFor(attr.getLocalAddress())));
275 if (attr.getLocalAddress6() != null) {
276 prefBuilder.setPrefix(new IpPrefix(IetfInetUtil.INSTANCE.ipv6PrefixFor(attr.getLocalAddress6())));
278 Prefix prefix = prefBuilder.build();
280 /* Add the Edge in the Connected Graph */
281 LOG.info("Add Edge {} and associated Prefix {} in TED[{}]", edge.getName(), prefix.getPrefix(), cgraph);
282 cgraph.addEdge(edge);
283 cgraph.addPrefix(prefix);
287 * Create Edge Attributes from Link attributes.
289 * @param la Linkstate Attributes
290 * @param linkDesc Linkstate Descriptors
292 * @return EdgeAttributes
294 private static EdgeAttributes createEdgeAttributes(final LinkAttributes la, final LinkDescriptors linkDesc) {
295 EdgeAttributesBuilder builder = new EdgeAttributesBuilder();
297 if (linkDesc.getIpv4InterfaceAddress() != null) {
298 builder.setLocalAddress(linkDesc.getIpv4InterfaceAddress());
300 if (linkDesc.getIpv6InterfaceAddress() != null) {
301 builder.setLocalAddress6(linkDesc.getIpv6InterfaceAddress());
303 if (linkDesc.getIpv4NeighborAddress() != null) {
304 builder.setRemoteAddress(linkDesc.getIpv4NeighborAddress());
306 if (linkDesc.getIpv6NeighborAddress() != null) {
307 builder.setRemoteAddress6(linkDesc.getIpv6NeighborAddress());
309 if (linkDesc.getLinkLocalIdentifier() != null) {
310 builder.setLocalIdentifier(linkDesc.getLinkLocalIdentifier());
312 if (linkDesc.getLinkRemoteIdentifier() != null) {
313 builder.setRemoteIdentifier(linkDesc.getLinkRemoteIdentifier());
315 if (la.getMetric() != null) {
316 builder.setMetric(la.getMetric().getValue());
318 if (la.getTeMetric() != null) {
319 builder.setTeMetric(la.getTeMetric().getValue());
321 if (la.getMaxLinkBandwidth() != null) {
322 builder.setMaxLinkBandwidth(bandwithToDecimalBandwidth(la.getMaxLinkBandwidth()));
324 if (la.getMaxReservableBandwidth() != null) {
325 builder.setMaxResvLinkBandwidth(bandwithToDecimalBandwidth(la.getMaxReservableBandwidth()));
327 if (la.getUnreservedBandwidth() != null) {
328 int upperBound = Math.min(la.getUnreservedBandwidth().size(), MAX_PRIORITY);
329 final List<UnreservedBandwidth> unRsvBw = new ArrayList<>(upperBound);
331 for (final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120
332 .UnreservedBandwidth bandwidth : la.nonnullUnreservedBandwidth().values()) {
333 unRsvBw.add(new UnreservedBandwidthBuilder()
334 .setBandwidth(bandwithToDecimalBandwidth(bandwidth.getBandwidth()))
335 .withKey(new UnreservedBandwidthKey(bandwidth.getPriority())).build());
337 builder.setUnreservedBandwidth(unRsvBw);
339 if (la.getAdminGroup() != null) {
340 builder.setAdminGroup(la.getAdminGroup().getValue());
342 if (la.getLinkDelay() != null) {
343 builder.setDelay(new Delay(la.getLinkDelay().getValue()));
345 if (la.getLinkMinMaxDelay() != null && la.getLinkMinMaxDelay() != null) {
346 MinMaxDelay mmDelay = new MinMaxDelayBuilder()
347 .setMaxDelay(new Delay(la.getLinkMinMaxDelay().getMaxDelay().getValue()))
348 .setMinDelay(new Delay(la.getLinkMinMaxDelay().getMinDelay().getValue())).build();
349 builder.setMinMaxDelay(mmDelay);
351 if (la.getDelayVariation() != null) {
352 builder.setJitter(new Delay(la.getDelayVariation().getValue()));
354 if (la.getLinkLoss() != null) {
355 builder.setLoss(new Loss(la.getLinkLoss().getValue()));
357 if (la.getAvailableBandwidth() != null) {
358 builder.setAvailableBandwidth(bandwithToDecimalBandwidth(la.getAvailableBandwidth()));
360 if (la.getResidualBandwidth() != null) {
361 builder.setResidualBandwidth(bandwithToDecimalBandwidth(la.getResidualBandwidth()));
363 if (la.getUtilizedBandwidth() != null) {
364 builder.setUtilizedBandwidth(bandwithToDecimalBandwidth(la.getUtilizedBandwidth()));
366 if (la.getSharedRiskLinkGroups() != null) {
367 final var srlgs = ImmutableSet.<Uint32>builder();
368 for (SrlgId srlg : la.getSharedRiskLinkGroups()) {
369 srlgs.add(srlg.getValue());
371 builder.setSrlgs(srlgs.build());
373 for (SrAdjIds adj : la.nonnullSrAdjIds()) {
374 if (adj.getSidLabelIndex() instanceof LocalLabelCase) {
375 boolean backup = false;
376 boolean ipv6 = false;
377 if (adj.getFlags() instanceof OspfAdjFlagsCase) {
378 backup = ((OspfAdjFlagsCase) adj.getFlags()).getOspfAdjFlags().getBackup();
380 if (adj.getFlags() instanceof IsisAdjFlagsCase) {
381 backup = ((IsisAdjFlagsCase) adj.getFlags()).getIsisAdjFlags().getBackup();
382 ipv6 = ((IsisAdjFlagsCase) adj.getFlags()).getIsisAdjFlags().getAddressFamily();
384 final Uint32 adjSid = ((LocalLabelCase) adj.getSidLabelIndex()).getLocalLabel().getValue();
387 builder.setAdjSid(adjSid);
389 builder.setAdjSid6(adjSid);
393 builder.setBackupAdjSid(adjSid);
395 builder.setBackupAdjSid6(adjSid);
400 return builder.build();
404 * Get Node Attributes from Link State Route attributes.
406 * @param attributes The attribute part from the Link State route
408 * @return Node Attributes
410 private static NodeAttributes getNodeAttributes(final Attributes attributes) {
411 final NodeAttributes na;
412 final Attributes1 attr = attributes.augmentation(Attributes1.class);
414 final LinkStateAttribute attrType = attr.getLinkStateAttribute();
415 if (attrType != null) {
416 na = ((NodeAttributesCase) attrType).getNodeAttributes();
427 * Create Vertex from the Node Attributes.
429 * @param na Node Attributes
430 * @param cvertex Connected Vertex associated to this Vertex
431 * @param as As number
435 private static Vertex getVertex(final NodeAttributes na, final Uint64 id, final Uint32 as) {
436 VertexBuilder builder = new VertexBuilder().setVertexId(id).setAsn(as);
437 if (na.getIpv4RouterId() != null) {
438 builder.setRouterId(na.getIpv4RouterId());
440 if (na.getIpv6RouterId() != null) {
441 builder.setRouterId6(na.getIpv6RouterId());
444 * Set Router Name with dynamic hostname (IS-IS) or IPv4 address in dot decimal format (OSPF)
446 if (na.getDynamicHostname() != null) {
447 builder.setName(na.getDynamicHostname());
449 int key = id.intValue();
451 (key << 24 & 0xFF) + "." + (key << 16 & 0xFF) + "." + (key << 8 & 0xFF) + "." + (key & 0xFF));
453 if (na.getSrCapabilities() != null) {
454 final SidLabelIndex labelIndex = na.getSrCapabilities().getSidLabelIndex();
455 if (labelIndex instanceof LocalLabelCase) {
456 builder.setSrgb(new SrgbBuilder()
457 .setLowerBound(((LocalLabelCase) labelIndex).getLocalLabel().getValue())
458 .setRangeSize(na.getSrCapabilities().getRangeSize().getValue())
460 } else if (labelIndex instanceof SidCase) {
461 builder.setSrgb(new SrgbBuilder()
462 .setLowerBound(((SidCase) labelIndex).getSid())
463 .setRangeSize(na.getSrCapabilities().getRangeSize().getValue())
467 if (na.getNodeFlags() != null) {
468 if (na.getNodeFlags().getAbr()) {
469 builder.setVertexType(VertexType.Abr);
471 if (na.getNodeFlags().getExternal()) {
472 builder.setVertexType(VertexType.AsbrOut);
475 builder.setVertexType(VertexType.Standard);
477 return builder.build();
481 * Create new Connected Vertex in the Connected Graph.
483 * @param value The complete Linkstate route information
484 * @param nodeCase The node part of the Linkstate route
485 * @param attributes The node attributes
487 private void createVertex(final LinkstateRoute value, final NodeCase nodeCase, final Attributes attributes) {
488 checkArgument(nodeCase != null, "Missing Node Case. Skip this Node");
489 checkArgument(nodeCase.getNodeDescriptors() != null, "Missing Node Descriptors. Skip this Node");
491 Uint64 vertexId = getVertexId(nodeCase.getNodeDescriptors().getCRouterIdentifier());
492 if (vertexId == Uint64.ZERO) {
493 LOG.warn("Unable to get Vertex Identifier from descriptor {}, skipping it", nodeCase.getNodeDescriptors());
497 NodeAttributes na = getNodeAttributes(attributes);
499 LOG.warn("Missing attributes in node {} route {}, skipping it", nodeCase, value);
503 Uint32 asNumber = Uint32.ZERO;
504 if (nodeCase.getNodeDescriptors() != null) {
505 asNumber = nodeCase.getNodeDescriptors().getAsNumber().getValue();
507 Vertex vertex = getVertex(na, vertexId, asNumber);
509 /* Add the Connected Vertex and associated Vertex in the Graph */
510 LOG.info("Add Vertex {} in TED[{}]", vertex.getName(), cgraph);
511 cgraph.addVertex(vertex);
515 * Create new Prefix in the Connected Graph.
517 * @param value The complete Linkstate route information
518 * @param prefixCase The Prefix part of the Linkstate route
519 * @param attributes The Prefix attributes
521 private void createPrefix(final LinkstateRoute value, final PrefixCase prefixCase, final Attributes attributes) {
522 final IpPrefix ippfx = prefixCase.getPrefixDescriptors().getIpReachabilityInformation();
524 LOG.warn("IP reachability not present in prefix {} route {}, skipping it", prefixCase, value);
528 /* Verify that all mandatory information are present */
529 final PrefixAttributes pa;
530 final Attributes1 attr = attributes.augmentation(Attributes1.class);
532 final LinkStateAttribute attrType = attr.getLinkStateAttribute();
533 if (attrType instanceof PrefixAttributesCase) {
534 pa = ((PrefixAttributesCase) attrType).getPrefixAttributes();
536 LOG.warn("Missing attribute type in IP {} prefix {} route {}, skipping it", ippfx, prefixCase, value);
540 LOG.warn("Missing attributes in IP {} prefix {} route {}, skipping it", ippfx, prefixCase, value);
545 * Get Connected Vertex from Connected Graph corresponding to the
546 * Advertising Node Descriptor
548 Uint64 vertexId = getVertexId(prefixCase.getAdvertisingNodeDescriptors().getCRouterIdentifier());
549 if (vertexId == Uint64.ZERO) {
550 LOG.warn("Unable to get the Vertex Identifier from descriptor {}, skipping it",
551 prefixCase.getAdvertisingNodeDescriptors());
556 PrefixBuilder builder = new PrefixBuilder().setVertexId(vertexId).setPrefix(ippfx);
557 if (pa.getSrPrefix() != null && pa.getSrPrefix().getSidLabelIndex() instanceof SidCase) {
558 builder.setPrefixSid(((SidCase) pa.getSrPrefix().getSidLabelIndex()).getSid());
559 if (pa.getSrPrefix().getFlags() instanceof IsisPrefixFlagsCase) {
561 ((IsisPrefixFlagsCase) pa.getSrPrefix().getFlags()).getIsisPrefixFlags().getNodeSid());
564 * Seems that OSPF Flags are not accessible. Assuming that the
565 * Prefix is a Node SID
567 builder.setNodeSid(true);
570 Prefix prefix = builder.build();
572 /* Add the Prefix to the Connected Vertex within the Connected Graph */
573 LOG.info("Add prefix {} in TED[{}]", builder.getPrefix(), cgraph);
574 cgraph.addPrefix(prefix);
578 protected void removeObject(final ReadWriteTransaction trans, final InstanceIdentifier<LinkstateRoute> id,
579 final LinkstateRoute value) {
581 LOG.error("Empty before-data received in delete data change notification for instance id {}", id);
585 final ObjectType t = value.getObjectType();
586 if (t instanceof LinkCase) {
587 removeEdge((LinkCase) t);
588 } else if (t instanceof NodeCase) {
589 removeVertex((NodeCase) t);
590 } else if (t instanceof PrefixCase) {
591 removePrefix((PrefixCase) t);
593 LOG.debug(UNHANDLED_OBJECT_CLASS, t.implementedInterface());
597 private void removeEdge(final LinkCase linkCase) {
598 /* Get Source and Destination Connected Vertex */
599 if (linkCase.getLinkDescriptors() == null) {
600 LOG.warn("Missing Link descriptor in link {}, skipping it", linkCase);
603 EdgeKey edgeKey = new EdgeKey(getEdgeId(linkCase));
604 if (edgeKey == null || edgeKey.getEdgeId() == Uint64.ZERO) {
605 LOG.warn("Unable to get the Edge Key from link {}, skipping it", linkCase);
609 LOG.info("Deleted Edge {} from TED[{}]", edgeKey, cgraph);
610 cgraph.deleteEdge(edgeKey);
613 private void removeVertex(final NodeCase nodeCase) {
614 VertexKey vertexKey = new VertexKey(getVertexId(nodeCase.getNodeDescriptors().getCRouterIdentifier()));
615 if (vertexKey == null || vertexKey.getVertexId() == Uint64.ZERO) {
616 LOG.warn("Unable to get Vertex Key from descriptor {}, skipping it", nodeCase.getNodeDescriptors());
620 LOG.info("Deleted Vertex {} in TED[{}]", vertexKey, cgraph);
621 cgraph.deleteVertex(vertexKey);
624 private void removePrefix(final PrefixCase prefixCase) {
625 final IpPrefix ippfx = prefixCase.getPrefixDescriptors().getIpReachabilityInformation();
627 LOG.warn("IP reachability not present in prefix {}, skipping it", prefixCase);
631 LOG.info("Deleted prefix {} in TED[{}]", ippfx, cgraph);
632 cgraph.deletePrefix(ippfx);
636 * Get Vertex in the Graph by the OSPF Router ID or IS-IS-System ID.
638 * @param routerID The Router Identifier entry
640 * @return Vertex in the Connected Graph that corresponds to this Router ID. Vertex is created if not found.
642 private static Uint64 getVertexId(final CRouterIdentifier routerID) {
643 Uint64 rid = Uint64.ZERO;
645 if (routerID instanceof IsisNodeCase) {
646 final byte[] isoId = ((IsisNodeCase) routerID).getIsisNode().getIsoSystemId().getValue();
647 final byte[] convert = {0, 0, isoId[0], isoId[1], isoId[2], isoId[3], isoId[4], isoId[5]};
648 rid = Uint64.fromLongBits(ByteBuffer.wrap(convert).getLong());
650 if (routerID instanceof OspfNodeCase) {
651 rid = ((OspfNodeCase) routerID).getOspfNode().getOspfRouterId().toUint64();
654 LOG.debug("Get Vertex Identifier {}", rid);
658 private static DecimalBandwidth bandwithToDecimalBandwidth(final Bandwidth bw) {
659 return new DecimalBandwidth(ProtocolUtil.bandwidthToDecimal64(bw));
662 private static Uint64 ipv4ToKey(final Ipv4InterfaceIdentifier ifId) {
663 return Uint32.fromIntBits(IetfInetUtil.INSTANCE.ipv4AddressNoZoneBits(ifId)).toUint64();
667 static Uint64 ipv6ToKey(final Ipv6InterfaceIdentifier ifId) {
668 final byte[] ip = IetfInetUtil.INSTANCE.ipv6AddressNoZoneBytes(ifId);
669 // Keep only the lower 64bits from the IP address, i.e. we skip first Long.BYTES bytes
670 return Uint64.fromLongBits(ByteBuffer.wrap(ip, Long.BYTES, Long.BYTES).getLong());
674 protected InstanceIdentifier<LinkstateRoute> getRouteWildcard(final InstanceIdentifier<Tables> tablesId) {
675 return tablesId.child(LinkstateRoutesCase.class, LinkstateRoutes.class).child(LinkstateRoute.class);
679 protected void clearTopology() {