2 * Copyright (c) 2016 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
9 package org.opendaylight.groupbasedpolicy.ne.location.provider;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.List;
16 import javax.annotation.Nullable;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
20 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
21 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
22 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.groupbasedpolicy.util.IidFactory;
26 import org.opendaylight.groupbasedpolicy.util.NetUtils;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocationBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.InternalLocationCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElements;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.NetworkElementsBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.NetworkElement;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element.Interface;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.network.elements.rev160407.network.elements.network.element._interface.EndpointNetwork;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
39 import org.opendaylight.yangtools.concepts.ListenerRegistration;
40 import org.opendaylight.yangtools.yang.binding.DataObject;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 import com.google.common.annotations.VisibleForTesting;
47 public class NeLocationProvider implements DataTreeChangeListener<NetworkElements>, AutoCloseable {
49 private static final Logger LOG = LoggerFactory.getLogger(NeLocationProvider.class);
50 public static final String NE_LOCATION_PROVIDER_NAME = "ne-location-provider";
52 private List<AddressEndpoint> endpoints;
53 private NetworkElements networkElements;
54 private DataBroker dataBroker;
55 private ListenerRegistration<NeLocationProvider> listenerRegistration;
56 private EndpointsListener endpointsListener;
58 public NeLocationProvider(DataBroker dataBroker) {
59 this.listenerRegistration =
60 dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
61 InstanceIdentifier.builder(NetworkElements.class).build()), this);
62 this.endpoints = new ArrayList<>();
63 this.networkElements = new NetworkElementsBuilder().build();
64 this.dataBroker = dataBroker;
65 this.endpointsListener = new EndpointsListener(dataBroker, this);
66 LOG.info("NE location provider created");
71 this.listenerRegistration.close();
72 this.endpointsListener.close();
75 public synchronized void onEndpointsChange(Collection<DataTreeModification<AddressEndpoint>> changes) {
76 for (DataTreeModification<AddressEndpoint> change : changes) {
77 switch (change.getRootNode().getModificationType()) {
79 AddressEndpoint endpoint = change.getRootNode().getDataBefore();
80 removeLocationForEndpoint(endpoint);
81 this.endpoints.remove(endpoint);
85 AddressEndpoint endpoint = change.getRootNode().getDataBefore();
86 if (endpoint != null) {
87 this.endpoints.remove(endpoint);
88 this.endpoints.add(change.getRootNode().getDataAfter());
91 endpoint = change.getRootNode().getDataAfter();
92 createLocationForEndpoint(endpoint);
93 this.endpoints.add(endpoint);
96 case SUBTREE_MODIFIED: {
97 this.endpoints.remove(change.getRootNode().getDataBefore());
98 this.endpoints.add(change.getRootNode().getDataAfter());
105 private void createLocationForEndpoint(AddressEndpoint endpoint) {
106 for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
107 for (Interface iface : nullToEmpty(ne.getInterface())) {
108 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
109 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
110 && endpoint.getContextId().equals(en.getL3ContextId())
111 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
112 .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
113 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
114 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
115 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
116 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
117 .child(AbsoluteLocation.class)
119 wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(ne.getIid(), iface.getIid()),
122 LOG.debug("New location created for endpoint {}", endpoint);
130 private void removeLocationForEndpoint(AddressEndpoint endpoint) {
131 for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
132 for (Interface iface : nullToEmpty(ne.getInterface())) {
133 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
134 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
135 && endpoint.getContextId().equals(en.getL3ContextId())
136 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
137 .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
138 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
139 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
140 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
141 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
142 .child(AbsoluteLocation.class)
144 wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
146 LOG.debug("Location deleted for endpoint {}", endpoint);
155 public synchronized void onDataTreeChanged(Collection<DataTreeModification<NetworkElements>> changes) {
156 for (DataTreeModification<NetworkElements> change : changes) {
157 switch (change.getRootNode().getModificationType()) {
159 NetworkElements nes = change.getRootNode().getDataBefore();
160 for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
161 for (Interface iface : nullToEmpty(ne.getInterface())) {
162 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
163 processDeletedEN(en);
167 networkElements = new NetworkElementsBuilder().build();
168 LOG.debug("Network elements removed");
172 NetworkElements nes = change.getRootNode().getDataBefore();
174 for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
175 for (Interface iface : nullToEmpty(ne.getInterface())) {
176 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
177 processDeletedEN(en);
182 nes = change.getRootNode().getDataAfter();
183 for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
184 for (Interface iface : nullToEmpty(ne.getInterface())) {
185 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
186 processCreatedEN(en, ne.getIid(), iface.getIid());
190 networkElements = nes;
191 LOG.debug("New Network elements created {}", change.getRootNode().getDataAfter());
194 case SUBTREE_MODIFIED: {
195 List<DataObjectModification<NetworkElement>> modifiedNetworkElements =
196 getModifiedNetworkElements(change.getRootNode());
197 for (DataObjectModification<NetworkElement> netElement : modifiedNetworkElements) {
198 processNetworkElementChange(netElement);
206 private List<DataObjectModification<NetworkElement>> getModifiedNetworkElements(
207 DataObjectModification<NetworkElements> modifiedNEs) {
208 Collection<DataObjectModification<? extends DataObject>> potentialModifiedNetworkElements =
209 modifiedNEs.getModifiedChildren();
210 if (potentialModifiedNetworkElements == null) {
211 return Collections.emptyList();
213 List<DataObjectModification<NetworkElement>> nes = new ArrayList<>();
214 for (DataObjectModification<? extends DataObject> potentialModifiedNetworkElement : potentialModifiedNetworkElements) {
215 if (potentialModifiedNetworkElement.getDataType().isAssignableFrom(NetworkElement.class)) {
216 nes.add((DataObjectModification<NetworkElement>) potentialModifiedNetworkElement);
222 private void processNetworkElementChange(DataObjectModification<NetworkElement> netElement) {
223 switch (netElement.getModificationType()) {
225 NetworkElement ne = netElement.getDataBefore();
226 for (Interface iface : nullToEmpty(ne.getInterface())) {
227 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
228 processDeletedEN(en);
231 networkElements.getNetworkElement().remove(ne);
232 LOG.debug("Netowrk element {} removed", netElement.getDataBefore());
236 NetworkElement ne = netElement.getDataBefore();
238 for (Interface iface : nullToEmpty(ne.getInterface())) {
239 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
240 processDeletedEN(en);
243 networkElements.getNetworkElement().remove(ne);
245 ne = netElement.getDataAfter();
246 for (Interface iface : nullToEmpty(ne.getInterface())) {
247 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
248 processCreatedEN(en, ne.getIid(), iface.getIid());
251 networkElements.getNetworkElement().add(ne);
252 LOG.debug("Created new Network element {}", netElement.getDataAfter());
255 case SUBTREE_MODIFIED: {
256 List<DataObjectModification<Interface>> modifiedInterfaces = getModifiedInterfaces(netElement);
257 for (DataObjectModification<Interface> modifiedInterface : modifiedInterfaces) {
258 processInterfaceChange(modifiedInterface, netElement.getDataBefore());
265 private List<DataObjectModification<Interface>> getModifiedInterfaces(
266 DataObjectModification<NetworkElement> netElement) {
267 Collection<DataObjectModification<? extends DataObject>> potentialModifiedInterfaces =
268 netElement.getModifiedChildren();
269 if (potentialModifiedInterfaces == null) {
270 return Collections.emptyList();
272 List<DataObjectModification<Interface>> interfaces = new ArrayList<>();
273 for (DataObjectModification<? extends DataObject> potentialModifiedInterface : potentialModifiedInterfaces) {
274 if (potentialModifiedInterface.getDataType().isAssignableFrom(Interface.class)) {
275 interfaces.add((DataObjectModification<Interface>) potentialModifiedInterface);
281 private void processInterfaceChange(DataObjectModification<Interface> modifiedInterface,
282 NetworkElement nodeBefore) {
283 switch (modifiedInterface.getModificationType()) {
285 Interface iface = modifiedInterface.getDataBefore();
286 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
287 processDeletedEN(en);
289 int nodeIndex = getIndexOf(nodeBefore);
290 networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
291 LOG.debug("Interface {} removed", modifiedInterface.getDataBefore());
295 Interface iface = modifiedInterface.getDataBefore();
296 int nodeIndex = getIndexOf(nodeBefore);
298 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
299 processDeletedEN(en);
301 networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
303 iface = modifiedInterface.getDataAfter();
304 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
305 processCreatedEN(en, nodeBefore.getIid(), iface.getIid());
307 networkElements.getNetworkElement().get(nodeIndex).getInterface().add(iface);
308 LOG.debug("Created new Interface {}", modifiedInterface.getDataAfter());
311 case SUBTREE_MODIFIED: {
312 List<DataObjectModification<EndpointNetwork>> modifiedENs =
313 getModifiedEndpointNetworks(modifiedInterface);
314 for (DataObjectModification<EndpointNetwork> modifiedEN : modifiedENs) {
315 processEndpointNetworkChange(modifiedEN, nodeBefore, modifiedInterface.getDataBefore());
322 private List<DataObjectModification<EndpointNetwork>> getModifiedEndpointNetworks(
323 DataObjectModification<Interface> modifiedInterface) {
324 Collection<DataObjectModification<? extends DataObject>> potentialModifiedEPs =
325 modifiedInterface.getModifiedChildren();
326 if (potentialModifiedEPs == null) {
327 return Collections.emptyList();
329 List<DataObjectModification<EndpointNetwork>> eps = new ArrayList<>();
330 for (DataObjectModification<? extends DataObject> potentialModifiedEP : potentialModifiedEPs) {
331 if (potentialModifiedEP.getDataType().isAssignableFrom(EndpointNetwork.class)) {
332 eps.add((DataObjectModification<EndpointNetwork>) potentialModifiedEP);
338 private void processEndpointNetworkChange(DataObjectModification<EndpointNetwork> modifiedEN,
339 NetworkElement nodeBefore, Interface ifaceBefore) {
340 switch (modifiedEN.getModificationType()) {
342 processDeletedEN(modifiedEN.getDataBefore());
343 int nodeIndex = getIndexOf(nodeBefore);
344 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
345 networkElements.getNetworkElement()
349 .getEndpointNetwork()
350 .remove(modifiedEN.getDataBefore());
351 LOG.debug("Endpoint network {} removed", modifiedEN.getDataBefore());
355 processCreatedEN(modifiedEN.getDataAfter(), nodeBefore.getIid(), ifaceBefore.getIid());
356 int nodeIndex = getIndexOf(nodeBefore);
357 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
358 networkElements.getNetworkElement()
362 .getEndpointNetwork()
363 .add(modifiedEN.getDataAfter());
364 LOG.debug("Created new Endpoint network {}", modifiedEN.getDataAfter());
367 case SUBTREE_MODIFIED: {
368 LOG.debug("EndpointNetwork {} changed", modifiedEN.getDataAfter().getKey());
374 private void processCreatedEN(EndpointNetwork en, InstanceIdentifier<?> nodeIID,
375 InstanceIdentifier<?> connectorIID) {
376 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
377 for (AddressEndpoint endpoint : endpoints) {
378 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
379 && endpoint.getContextId().equals(en.getL3ContextId())
380 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class)
381 && NetUtils.samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
382 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
383 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
384 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
385 .child(AbsoluteLocation.class)
387 wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(nodeIID, connectorIID), true);
389 LOG.debug("New location created for endpoint {}", endpoint);
395 private void processDeletedEN(EndpointNetwork en) {
396 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
397 for (AddressEndpoint endpoint : endpoints) {
398 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
399 && endpoint.getContextId().equals(en.getL3ContextId())
400 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class)
401 && NetUtils.samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
402 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
403 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
404 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
405 .child(AbsoluteLocation.class)
407 wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
409 LOG.debug("Location deleted for endpoint {}", endpoint);
415 private AbsoluteLocation createRealLocation(InstanceIdentifier<?> node, InstanceIdentifier<?> iface) {
416 return new AbsoluteLocationBuilder()
417 .setLocationType(new InternalLocationCaseBuilder().setInternalNode(node).setInternalNodeConnector(iface).build()).build();
420 private <T> List<T> nullToEmpty(@Nullable List<T> list) {
421 return list == null ? Collections.emptyList() : list;
424 private int getIndexOf(NetworkElement ne) {
425 for (NetworkElement listNE : networkElements.getNetworkElement()) {
426 if (ne.getIid().equals(listNE.getIid())) {
427 return networkElements.getNetworkElement().indexOf(listNE);
433 private int getIndexOf(Interface iface, int nodeIndex) {
434 for (Interface listIface : networkElements.getNetworkElement().get(nodeIndex).getInterface()) {
435 if (iface.getIid().equals(listIface.getIid())) {
436 return networkElements.getNetworkElement().get(nodeIndex).getInterface().indexOf(listIface);
443 synchronized List<AddressEndpoint> getEndpoints() {
448 synchronized NetworkElements getNetworkElements() {
449 return networkElements;