2 * Copyright (c) 2013 Cisco Systems, Inc. and others. 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.pcep.tunnel.provider;
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.Lists;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.JdkFutureAdapters;
16 import java.util.ArrayList;
17 import java.util.Collection;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
23 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
26 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
27 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.AdministrativeStatus;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Path1;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.lsp.identifiers.AddressFamily;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.lsp.identifiers.address.family.Ipv4Case;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.lsp.identifiers.address.family.Ipv6Case;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.lsp.identifiers.address.family.ipv4._case.Ipv4;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.identifiers.tlv.lsp.identifiers.address.family.ipv6._case.Ipv6;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsp;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.reported.lsp.Path;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.Link1;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.Link1Builder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.SupportingNode1;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.SupportingNode1Builder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.tunnel.pcep.rev130820.tunnel.pcep.supporting.node.attributes.PathComputationClientBuilder;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.DestinationBuilder;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.SourceBuilder;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNode;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeBuilder;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.node.attributes.SupportingNodeKey;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.TerminationPoint1;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.TerminationPoint1Builder;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.IgpTerminationPointAttributesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.igp.termination.point.attributes.TerminationPointType;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.igp.termination.point.attributes.termination.point.type.Ip;
71 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.termination.point.attributes.igp.termination.point.attributes.termination.point.type.IpBuilder;
72 import org.opendaylight.yangtools.yang.binding.DataObject;
73 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
78 public final class NodeChangedListener implements ClusteredDataTreeChangeListener<Node> {
79 private static final Logger LOG = LoggerFactory.getLogger(NodeChangedListener.class);
80 private final InstanceIdentifier<Topology> target;
81 private final DataBroker dataProvider;
82 private final TopologyId source;
84 NodeChangedListener(final DataBroker dataProvider, final TopologyId source, final InstanceIdentifier<Topology> target) {
85 this.dataProvider = Preconditions.checkNotNull(dataProvider);
86 this.target = Preconditions.checkNotNull(target);
87 this.source = Preconditions.checkNotNull(source);
90 private static void categorizeIdentifier(final InstanceIdentifier<?> i, final Set<InstanceIdentifier<ReportedLsp>> changedLsps,
91 final Set<InstanceIdentifier<Node>> changedNodes) {
92 final InstanceIdentifier<ReportedLsp> li = i.firstIdentifierOf(ReportedLsp.class);
94 final InstanceIdentifier<Node> ni = i.firstIdentifierOf(Node.class);
96 LOG.warn("Ignoring uncategorized identifier {}", i);
105 private static void enumerateLsps(final InstanceIdentifier<Node> id, final Node node, final Set<InstanceIdentifier<ReportedLsp>> lsps) {
107 LOG.trace("Skipping null node", id);
110 final Node1 pccnode = node.getAugmentation(Node1.class);
111 if (pccnode == null) {
112 LOG.trace("Skipping non-PCEP-enabled node {}", id);
116 for (final ReportedLsp l : pccnode.getPathComputationClient().getReportedLsp()) {
117 lsps.add(id.builder().augmentation(Node1.class).child(PathComputationClient.class).child(ReportedLsp.class, l.getKey()).build());
121 private static LinkId linkIdForLsp(final InstanceIdentifier<ReportedLsp> i, final ReportedLsp lsp) {
122 return new LinkId(i.firstKeyOf(Node.class, NodeKey.class).getNodeId().getValue() + "/lsps/" + lsp.getName());
125 private InstanceIdentifier<Link> linkForLsp(final LinkId linkId) {
126 return this.target.child(Link.class, new LinkKey(linkId));
129 private SupportingNode createSupportingNode(final NodeId sni, final Boolean inControl) {
130 final SupportingNodeKey sk = new SupportingNodeKey(sni, this.source);
131 final SupportingNodeBuilder snb = new SupportingNodeBuilder();
134 snb.addAugmentation(SupportingNode1.class, new SupportingNode1Builder().setPathComputationClient(
135 new PathComputationClientBuilder().setControlling(inControl).build()).build());
140 private void handleSni(final InstanceIdentifier<Node> sni, final Node n, final Boolean inControl, final ReadWriteTransaction trans) {
142 final NodeKey k = InstanceIdentifier.keyOf(sni);
143 boolean have = false;
145 * We may have found a termination point which has been created as a destination,
146 * so it does not have a supporting node pointer. Since we now know what it is,
149 if (n.getSupportingNode() != null) {
150 for (final SupportingNode sn : n.getSupportingNode()) {
151 if (sn.getNodeRef().equals(k.getNodeId())) {
158 final SupportingNode sn = createSupportingNode(k.getNodeId(), inControl);
159 trans.put(LogicalDatastoreType.OPERATIONAL, this.target.child(Node.class, n.getKey()).child(
160 SupportingNode.class, sn.getKey()), sn);
165 private InstanceIdentifier<TerminationPoint> getIpTerminationPoint(final ReadWriteTransaction trans, final IpAddress addr,
166 final InstanceIdentifier<Node> sni, final Boolean inControl) throws ReadFailedException {
167 final Topology topo = trans.read(LogicalDatastoreType.OPERATIONAL, this.target).checkedGet().get();
168 if (topo.getNode() != null) {
169 for (final Node n : topo.getNode()) {
170 if(n.getTerminationPoint() != null) {
171 for (final TerminationPoint tp : n.getTerminationPoint()) {
172 final TerminationPoint1 tpa = tp.getAugmentation(TerminationPoint1.class);
174 final TerminationPointType tpt = tpa.getIgpTerminationPointAttributes().getTerminationPointType();
175 if (tpt instanceof Ip) {
176 for (final IpAddress a : ((Ip) tpt).getIpAddress()) {
177 if (addr.equals(a)) {
178 handleSni(sni, n, inControl, trans);
179 return this.target.builder().child(Node.class, n.getKey()).child(TerminationPoint.class, tp.getKey()).build();
183 LOG.debug("Ignoring termination point type {}", tpt);
190 LOG.debug("Termination point for {} not found, creating a new one", addr);
191 return createTP(addr, sni, inControl, trans);
194 private InstanceIdentifier<TerminationPoint> createTP(final IpAddress addr, final InstanceIdentifier<Node> sni,
195 final Boolean inControl, final ReadWriteTransaction trans) {
196 final String url = "ip://" + addr.toString();
197 final TerminationPointKey tpk = new TerminationPointKey(new TpId(url));
198 final TerminationPointBuilder tpb = new TerminationPointBuilder();
199 tpb.setKey(tpk).setTpId(tpk.getTpId());
200 tpb.addAugmentation(TerminationPoint1.class, new TerminationPoint1Builder().setIgpTerminationPointAttributes(
201 new IgpTerminationPointAttributesBuilder().setTerminationPointType(
202 new IpBuilder().setIpAddress(Lists.newArrayList(addr)).build()).build()).build());
204 final NodeKey nk = new NodeKey(new NodeId(url));
205 final NodeBuilder nb = new NodeBuilder();
206 nb.setKey(nk).setNodeId(nk.getNodeId());
207 nb.setTerminationPoint(Lists.newArrayList(tpb.build()));
209 nb.setSupportingNode(Lists.newArrayList(createSupportingNode(InstanceIdentifier.keyOf(sni).getNodeId(), inControl)));
211 final InstanceIdentifier<Node> nid = this.target.child(Node.class, nb.getKey());
212 trans.put(LogicalDatastoreType.OPERATIONAL, nid, nb.build());
213 return nid.child(TerminationPoint.class, tpb.getKey());
216 private void create(final ReadWriteTransaction trans, final InstanceIdentifier<ReportedLsp> i, final ReportedLsp value) throws ReadFailedException {
217 final InstanceIdentifier<Node> ni = i.firstIdentifierOf(Node.class);
219 final Path1 rl = value.getPath().get(0).getAugmentation(Path1.class);
221 final AddressFamily af = rl.getLsp().getTlvs().getLspIdentifiers().getAddressFamily();
224 * We are trying to ensure we have source and destination nodes.
226 final IpAddress srcIp, dstIp;
227 if (af instanceof Ipv4Case) {
228 final Ipv4 ipv4 = ((Ipv4Case) af).getIpv4();
229 srcIp = new IpAddress(ipv4.getIpv4TunnelSenderAddress());
230 dstIp = new IpAddress(ipv4.getIpv4TunnelEndpointAddress());
231 } else if (af instanceof Ipv6Case) {
232 final Ipv6 ipv6 = ((Ipv6Case) af).getIpv6();
233 srcIp = new IpAddress(ipv6.getIpv6TunnelSenderAddress());
234 dstIp = new IpAddress(ipv6.getIpv6TunnelSenderAddress());
236 throw new IllegalArgumentException("Unsupported address family: " + af.getImplementedInterface());
239 final Path path0 = value.getPath().get(0);
240 final Link1Builder lab = new Link1Builder();
241 if (path0.getBandwidth() != null) {
242 lab.setBandwidth(path0.getBandwidth().getBandwidth());
244 if (path0.getClassType() != null) {
245 lab.setClassType(path0.getClassType().getClassType());
247 lab.setSymbolicPathName(value.getName());
249 final InstanceIdentifier<TerminationPoint> dst = getIpTerminationPoint(trans, dstIp, null, Boolean.FALSE);
250 final InstanceIdentifier<TerminationPoint> src = getIpTerminationPoint(trans, srcIp, ni, rl.getLsp().isDelegate());
252 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Link1Builder slab = new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Link1Builder();
253 slab.setOperationalStatus(rl.getLsp().getOperational());
254 slab.setAdministrativeStatus(rl.getLsp().isAdministrative() ? AdministrativeStatus.Active : AdministrativeStatus.Inactive);
256 final LinkId id = linkIdForLsp(i, value);
257 final LinkBuilder lb = new LinkBuilder();
260 lb.setSource(new SourceBuilder().setSourceNode(src.firstKeyOf(Node.class, NodeKey.class).getNodeId()).setSourceTp(
261 src.firstKeyOf(TerminationPoint.class, TerminationPointKey.class).getTpId()).build());
262 lb.setDestination(new DestinationBuilder().setDestNode(dst.firstKeyOf(Node.class, NodeKey.class).getNodeId()).setDestTp(
263 dst.firstKeyOf(TerminationPoint.class, TerminationPointKey.class).getTpId()).build());
264 lb.addAugmentation(Link1.class, lab.build());
265 lb.addAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.Link1.class,
268 trans.put(LogicalDatastoreType.OPERATIONAL, linkForLsp(id), lb.build());
271 private InstanceIdentifier<TerminationPoint> tpIdentifier(final NodeId node, final TpId tp) {
272 return this.target.builder().child(Node.class, new NodeKey(node)).child(TerminationPoint.class, new TerminationPointKey(tp)).build();
275 private InstanceIdentifier<Node> nodeIdentifier(final NodeId node) {
276 return this.target.child(Node.class, new NodeKey(node));
279 private void remove(final ReadWriteTransaction trans, final InstanceIdentifier<ReportedLsp> i, final ReportedLsp value) throws ReadFailedException {
280 final InstanceIdentifier<Link> li = linkForLsp(linkIdForLsp(i, value));
282 final Optional<Link> ol = trans.read(LogicalDatastoreType.OPERATIONAL, li).checkedGet();
283 if (!ol.isPresent()) {
287 final Link l = ol.get();
288 LOG.debug("Removing link {} (was {})", li, l);
289 trans.delete(LogicalDatastoreType.OPERATIONAL, li);
291 LOG.debug("Searching for orphan links/nodes");
292 final Optional<Topology> ot = trans.read(LogicalDatastoreType.OPERATIONAL, this.target).checkedGet();
293 Preconditions.checkState(ot.isPresent());
295 final Topology t = ot.get();
296 final NodeId srcNode = l.getSource().getSourceNode();
297 final NodeId dstNode = l.getDestination().getDestNode();
298 final TpId srcTp = l.getSource().getSourceTp();
299 final TpId dstTp = l.getDestination().getDestTp();
301 boolean orphSrcNode = true, orphDstNode = true, orphDstTp = true, orphSrcTp = true;
302 for (final Link lw : t.getLink()) {
303 LOG.trace("Checking link {}", lw);
305 final NodeId sn = lw.getSource().getSourceNode();
306 final NodeId dn = lw.getDestination().getDestNode();
307 final TpId st = lw.getSource().getSourceTp();
308 final TpId dt = lw.getDestination().getDestTp();
310 // Source node checks
311 if (srcNode.equals(sn)) {
313 LOG.debug("Node {} held by source of link {}", srcNode, lw);
316 if (orphSrcTp && srcTp.equals(st)) {
317 LOG.debug("TP {} held by source of link {}", srcTp, lw);
321 if (srcNode.equals(dn)) {
323 LOG.debug("Node {} held by destination of link {}", srcNode, lw);
326 if (orphSrcTp && srcTp.equals(dt)) {
327 LOG.debug("TP {} held by destination of link {}", srcTp, lw);
332 // Destination node checks
333 if (dstNode.equals(sn)) {
335 LOG.debug("Node {} held by source of link {}", dstNode, lw);
338 if (orphDstTp && dstTp.equals(st)) {
339 LOG.debug("TP {} held by source of link {}", dstTp, lw);
343 if (dstNode.equals(dn)) {
345 LOG.debug("Node {} held by destination of link {}", dstNode, lw);
348 if (orphDstTp && dstTp.equals(dt)) {
349 LOG.debug("TP {} held by destination of link {}", dstTp, lw);
355 if (orphSrcNode && !orphSrcTp) {
356 LOG.warn("Orphan source node {} but not TP {}, retaining the node", srcNode, srcTp);
359 if (orphDstNode && !orphDstTp) {
360 LOG.warn("Orphan destination node {} but not TP {}, retaining the node", dstNode, dstTp);
365 LOG.debug("Removing orphan node {}", srcNode);
366 trans.delete(LogicalDatastoreType.OPERATIONAL, nodeIdentifier(srcNode));
367 } else if (orphSrcTp) {
368 LOG.debug("Removing orphan TP {} on node {}", srcTp, srcNode);
369 trans.delete(LogicalDatastoreType.OPERATIONAL, tpIdentifier(srcNode, srcTp));
372 LOG.debug("Removing orphan node {}", dstNode);
373 trans.delete(LogicalDatastoreType.OPERATIONAL, nodeIdentifier(dstNode));
374 } else if (orphDstTp) {
375 LOG.debug("Removing orphan TP {} on node {}", dstTp, dstNode);
376 trans.delete(LogicalDatastoreType.OPERATIONAL, tpIdentifier(dstNode, dstTp));
381 public void onDataTreeChanged(final Collection<DataTreeModification<Node>> changes) {
382 final ReadWriteTransaction trans = this.dataProvider.newReadWriteTransaction();
384 final Set<InstanceIdentifier<ReportedLsp>> lsps = new HashSet<>();
385 final Set<InstanceIdentifier<Node>> nodes = new HashSet<>();
387 final Map<InstanceIdentifier<?>, DataObject> original = new HashMap<>();
388 final Map<InstanceIdentifier<?>, DataObject> updated = new HashMap<>();
389 final Map<InstanceIdentifier<?>, DataObject> created = new HashMap<>();
391 for (final DataTreeModification<?> change : changes) {
392 final InstanceIdentifier<?> iid = change.getRootPath().getRootIdentifier();
393 final DataObjectModification<?> rootNode = change.getRootNode();
394 handleChangedNode(rootNode, iid, lsps, nodes, original, updated, created);
397 // Now walk all nodes, check for removals/additions and cascade them to LSPs
398 for (final InstanceIdentifier<Node> iid : nodes) {
399 enumerateLsps(iid, (Node) original.get(iid), lsps);
400 enumerateLsps(iid, (Node) updated.get(iid), lsps);
401 enumerateLsps(iid, (Node) created.get(iid), lsps);
404 // We now have list of all affected LSPs. Walk them create/remove them
405 updateTransaction(trans, lsps, original, updated, created);
407 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(trans.submit()), new FutureCallback<Void>() {
409 public void onSuccess(final Void result) {
410 LOG.trace("Topology change committed successfully");
414 public void onFailure(final Throwable t) {
415 LOG.error("Failed to propagate a topology change, target topology became inconsistent", t);
420 private void handleChangedNode(final DataObjectModification<?> changedNode, final InstanceIdentifier<?> iid,
421 final Set<InstanceIdentifier<ReportedLsp>> lsps, final Set<InstanceIdentifier<Node>> nodes,
422 final Map<InstanceIdentifier<?>, DataObject> original, final Map<InstanceIdentifier<?>, DataObject> updated,
423 final Map<InstanceIdentifier<?>, DataObject> created) {
425 // Categorize reported identifiers
426 categorizeIdentifier(iid, lsps, nodes);
429 switch (changedNode.getModificationType()) {
431 original.put(iid, changedNode.getDataBefore());
433 case SUBTREE_MODIFIED:
434 original.put(iid, changedNode.getDataBefore());
435 updated.put(iid, changedNode.getDataAfter());
438 created.put(iid, changedNode.getDataAfter());
441 throw new IllegalArgumentException("Unhandled modification type " + changedNode.getModificationType());
444 for (DataObjectModification<? extends DataObject> child : changedNode.getModifiedChildren()) {
445 final List<PathArgument> pathArguments = new ArrayList<>();
446 for (PathArgument pathArgument : iid.getPathArguments()) {
447 pathArguments.add(pathArgument);
449 pathArguments.add(child.getIdentifier());
450 final InstanceIdentifier<?> childIID = InstanceIdentifier.create(pathArguments);
451 handleChangedNode(child, childIID, lsps, nodes, original, updated, created);
455 private void updateTransaction(final ReadWriteTransaction trans, final Set<InstanceIdentifier<ReportedLsp>> lsps,
456 final Map<InstanceIdentifier<?>, ? extends DataObject> old, final Map<InstanceIdentifier<?>, DataObject> updated,
457 final Map<InstanceIdentifier<?>, DataObject> created) {
459 for (final InstanceIdentifier<ReportedLsp> i : lsps) {
460 final ReportedLsp oldValue = (ReportedLsp) old.get(i);
461 ReportedLsp newValue = (ReportedLsp) updated.get(i);
462 if (newValue == null) {
463 newValue = (ReportedLsp) created.get(i);
466 LOG.debug("Updating lsp {} value {} -> {}", i, oldValue, newValue);
467 if (oldValue != null) {
469 remove(trans, i, oldValue);
470 } catch (final ReadFailedException e) {
471 LOG.warn("Failed to remove LSP {}", i, e);
474 if (newValue != null) {
476 create(trans, i, newValue);
477 } catch (final ReadFailedException e) {
478 LOG.warn("Failed to add LSP {}", i, e);
484 public static InstanceIdentifier<Link> linkIdentifier(final InstanceIdentifier<Topology> topology, final NodeId node, final String name) {
485 return topology.child(Link.class, new LinkKey(new LinkId(node.getValue() + "/lsp/" + name)));