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);
118 wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(ne.getIid(), iface.getIid()),
121 LOG.debug("New location created for endpoint {}", endpoint);
129 private void removeLocationForEndpoint(AddressEndpoint endpoint) {
130 for (NetworkElement ne : nullToEmpty(networkElements.getNetworkElement())) {
131 for (Interface iface : nullToEmpty(ne.getInterface())) {
132 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
133 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
134 && endpoint.getContextId().equals(en.getL3ContextId())
135 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class) && NetUtils
136 .samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
137 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
138 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
139 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
140 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
141 .child(AbsoluteLocation.class);
142 wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
144 LOG.debug("Location deleted for endpoint {}", endpoint);
153 public synchronized void onDataTreeChanged(Collection<DataTreeModification<NetworkElements>> changes) {
154 for (DataTreeModification<NetworkElements> change : changes) {
155 switch (change.getRootNode().getModificationType()) {
157 NetworkElements nes = change.getRootNode().getDataBefore();
158 for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
159 for (Interface iface : nullToEmpty(ne.getInterface())) {
160 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
161 processDeletedEN(en);
165 networkElements = new NetworkElementsBuilder().build();
166 LOG.debug("Network elements removed");
170 NetworkElements nes = change.getRootNode().getDataBefore();
172 for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
173 for (Interface iface : nullToEmpty(ne.getInterface())) {
174 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
175 processDeletedEN(en);
180 nes = change.getRootNode().getDataAfter();
181 for (NetworkElement ne : nullToEmpty(nes.getNetworkElement())) {
182 for (Interface iface : nullToEmpty(ne.getInterface())) {
183 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
184 processCreatedEN(en, ne.getIid(), iface.getIid());
188 networkElements = nes;
189 LOG.debug("New Network elements created {}", change.getRootNode().getDataAfter());
192 case SUBTREE_MODIFIED: {
193 List<DataObjectModification<NetworkElement>> modifiedNetworkElements =
194 getModifiedNetworkElements(change.getRootNode());
195 for (DataObjectModification<NetworkElement> netElement : modifiedNetworkElements) {
196 processNetworkElementChange(netElement);
204 private List<DataObjectModification<NetworkElement>> getModifiedNetworkElements(
205 DataObjectModification<NetworkElements> modifiedNEs) {
206 Collection<DataObjectModification<? extends DataObject>> potentialModifiedNetworkElements =
207 modifiedNEs.getModifiedChildren();
208 if (potentialModifiedNetworkElements == null) {
209 return Collections.emptyList();
211 List<DataObjectModification<NetworkElement>> nes = new ArrayList<>();
212 for (DataObjectModification<? extends DataObject> potentialModifiedNetworkElement : potentialModifiedNetworkElements) {
213 if (potentialModifiedNetworkElement.getDataType().isAssignableFrom(NetworkElement.class)) {
214 nes.add((DataObjectModification<NetworkElement>) potentialModifiedNetworkElement);
220 private void processNetworkElementChange(DataObjectModification<NetworkElement> netElement) {
221 switch (netElement.getModificationType()) {
223 NetworkElement ne = netElement.getDataBefore();
224 for (Interface iface : nullToEmpty(ne.getInterface())) {
225 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
226 processDeletedEN(en);
229 networkElements.getNetworkElement().remove(ne);
230 LOG.debug("Netowrk element {} removed", netElement.getDataBefore());
234 NetworkElement ne = netElement.getDataBefore();
236 for (Interface iface : nullToEmpty(ne.getInterface())) {
237 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
238 processDeletedEN(en);
241 networkElements.getNetworkElement().remove(ne);
243 ne = netElement.getDataAfter();
244 for (Interface iface : nullToEmpty(ne.getInterface())) {
245 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
246 processCreatedEN(en, ne.getIid(), iface.getIid());
249 networkElements.getNetworkElement().add(ne);
250 LOG.debug("Created new Network element {}", netElement.getDataAfter());
253 case SUBTREE_MODIFIED: {
254 List<DataObjectModification<Interface>> modifiedInterfaces = getModifiedInterfaces(netElement);
255 for (DataObjectModification<Interface> modifiedInterface : modifiedInterfaces) {
256 processInterfaceChange(modifiedInterface, netElement.getDataBefore());
263 private List<DataObjectModification<Interface>> getModifiedInterfaces(
264 DataObjectModification<NetworkElement> netElement) {
265 Collection<DataObjectModification<? extends DataObject>> potentialModifiedInterfaces =
266 netElement.getModifiedChildren();
267 if (potentialModifiedInterfaces == null) {
268 return Collections.emptyList();
270 List<DataObjectModification<Interface>> interfaces = new ArrayList<>();
271 for (DataObjectModification<? extends DataObject> potentialModifiedInterface : potentialModifiedInterfaces) {
272 if (potentialModifiedInterface.getDataType().isAssignableFrom(Interface.class)) {
273 interfaces.add((DataObjectModification<Interface>) potentialModifiedInterface);
279 private void processInterfaceChange(DataObjectModification<Interface> modifiedInterface,
280 NetworkElement nodeBefore) {
281 switch (modifiedInterface.getModificationType()) {
283 Interface iface = modifiedInterface.getDataBefore();
284 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
285 processDeletedEN(en);
287 int nodeIndex = getIndexOf(nodeBefore);
288 networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
289 LOG.debug("Interface {} removed", modifiedInterface.getDataBefore());
293 Interface iface = modifiedInterface.getDataBefore();
294 int nodeIndex = getIndexOf(nodeBefore);
296 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
297 processDeletedEN(en);
299 networkElements.getNetworkElement().get(nodeIndex).getInterface().remove(iface);
301 iface = modifiedInterface.getDataAfter();
302 for (EndpointNetwork en : nullToEmpty(iface.getEndpointNetwork())) {
303 processCreatedEN(en, nodeBefore.getIid(), iface.getIid());
305 networkElements.getNetworkElement().get(nodeIndex).getInterface().add(iface);
306 LOG.debug("Created new Interface {}", modifiedInterface.getDataAfter());
309 case SUBTREE_MODIFIED: {
310 List<DataObjectModification<EndpointNetwork>> modifiedENs =
311 getModifiedEndpointNetworks(modifiedInterface);
312 for (DataObjectModification<EndpointNetwork> modifiedEN : modifiedENs) {
313 processEndpointNetworkChange(modifiedEN, nodeBefore, modifiedInterface.getDataBefore());
320 private List<DataObjectModification<EndpointNetwork>> getModifiedEndpointNetworks(
321 DataObjectModification<Interface> modifiedInterface) {
322 Collection<DataObjectModification<? extends DataObject>> potentialModifiedEPs =
323 modifiedInterface.getModifiedChildren();
324 if (potentialModifiedEPs == null) {
325 return Collections.emptyList();
327 List<DataObjectModification<EndpointNetwork>> eps = new ArrayList<>();
328 for (DataObjectModification<? extends DataObject> potentialModifiedEP : potentialModifiedEPs) {
329 if (potentialModifiedEP.getDataType().isAssignableFrom(EndpointNetwork.class)) {
330 eps.add((DataObjectModification<EndpointNetwork>) potentialModifiedEP);
336 private void processEndpointNetworkChange(DataObjectModification<EndpointNetwork> modifiedEN,
337 NetworkElement nodeBefore, Interface ifaceBefore) {
338 switch (modifiedEN.getModificationType()) {
340 processDeletedEN(modifiedEN.getDataBefore());
341 int nodeIndex = getIndexOf(nodeBefore);
342 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
343 networkElements.getNetworkElement()
347 .getEndpointNetwork()
348 .remove(modifiedEN.getDataBefore());
349 LOG.debug("Endpoint network {} removed", modifiedEN.getDataBefore());
353 processCreatedEN(modifiedEN.getDataAfter(), nodeBefore.getIid(), ifaceBefore.getIid());
354 int nodeIndex = getIndexOf(nodeBefore);
355 int ifaceIndex = getIndexOf(ifaceBefore, nodeIndex);
356 networkElements.getNetworkElement()
360 .getEndpointNetwork()
361 .add(modifiedEN.getDataAfter());
362 LOG.debug("Created new Endpoint network {}", modifiedEN.getDataAfter());
365 case SUBTREE_MODIFIED: {
366 LOG.debug("EndpointNetwork {} changed", modifiedEN.getDataAfter().getKey());
372 private void processCreatedEN(EndpointNetwork en, InstanceIdentifier<?> nodeIID,
373 InstanceIdentifier<?> connectorIID) {
374 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
375 for (AddressEndpoint endpoint : endpoints) {
376 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
377 && endpoint.getContextId().equals(en.getL3ContextId())
378 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class)
379 && NetUtils.samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
380 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
381 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
382 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
383 .child(AbsoluteLocation.class);
384 wtx.put(LogicalDatastoreType.OPERATIONAL, iid, createRealLocation(nodeIID, connectorIID), true);
386 LOG.debug("New location created for endpoint {}", endpoint);
392 private void processDeletedEN(EndpointNetwork en) {
393 WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
394 for (AddressEndpoint endpoint : endpoints) {
395 if (endpoint.getContextType().isAssignableFrom(L3Context.class)
396 && endpoint.getContextId().equals(en.getL3ContextId())
397 && endpoint.getAddressType().isAssignableFrom(IpPrefixType.class)
398 && NetUtils.samePrefix(new IpPrefix(endpoint.getAddress().toCharArray()), en.getIpPrefix())) {
399 InstanceIdentifier<AbsoluteLocation> iid = IidFactory
400 .providerAddressEndpointLocationIid(NE_LOCATION_PROVIDER_NAME, IpPrefixType.class,
401 endpoint.getAddress(), endpoint.getContextType(), endpoint.getContextId())
402 .child(AbsoluteLocation.class);
403 wtx.delete(LogicalDatastoreType.OPERATIONAL, iid);
405 LOG.debug("Location deleted for endpoint {}", endpoint);
411 private AbsoluteLocation createRealLocation(InstanceIdentifier<?> node, InstanceIdentifier<?> iface) {
412 return new AbsoluteLocationBuilder()
413 .setLocationType(new InternalLocationCaseBuilder().setInternalNode(node).setInternalNodeConnector(iface).build()).build();
416 private <T> List<T> nullToEmpty(@Nullable List<T> list) {
417 return list == null ? Collections.emptyList() : list;
420 private int getIndexOf(NetworkElement ne) {
421 for (NetworkElement listNE : networkElements.getNetworkElement()) {
422 if (ne.getIid().equals(listNE.getIid())) {
423 return networkElements.getNetworkElement().indexOf(listNE);
429 private int getIndexOf(Interface iface, int nodeIndex) {
430 for (Interface listIface : networkElements.getNetworkElement().get(nodeIndex).getInterface()) {
431 if (iface.getIid().equals(listIface.getIid())) {
432 return networkElements.getNetworkElement().get(nodeIndex).getInterface().indexOf(listIface);
439 synchronized List<AddressEndpoint> getEndpoints() {
444 synchronized NetworkElements getNetworkElements() {
445 return networkElements;