Merge "Adding dest IP/MAC in ArpResponseReceived"
[genius.git] / interfacemanager / interfacemanager-impl / src / main / java / org / opendaylight / genius / interfacemanager / listeners / InterfaceConfigListener.java
1 /*
2  * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.genius.interfacemanager.listeners;
10
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.util.List;
13 import java.util.concurrent.Callable;
14 import javax.inject.Inject;
15 import javax.inject.Singleton;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
19 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
20 import org.opendaylight.genius.interfacemanager.IfmConstants;
21 import org.opendaylight.genius.interfacemanager.InterfacemgrProvider;
22 import org.opendaylight.genius.interfacemanager.commons.InterfaceManagerCommonUtils;
23 import org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
24 import org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
25 import org.opendaylight.genius.interfacemanager.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
26 import org.opendaylight.genius.interfacemanager.renderer.ovs.utilities.IfmClusterUtils;
27 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.alivenessmonitor.rev160411.AlivenessMonitorService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * This class listens for interface creation/removal/update in Configuration DS.
39  * This is used to handle interfaces for base of-ports.
40  */
41 @Singleton
42 public class InterfaceConfigListener
43         extends AsyncClusteredDataTreeChangeListenerBase<Interface, InterfaceConfigListener> {
44     private static final Logger LOG = LoggerFactory.getLogger(InterfaceConfigListener.class);
45     private final DataBroker dataBroker;
46     private final IdManagerService idManager;
47     private final AlivenessMonitorService alivenessMonitorService;
48     private final IMdsalApiManager mdsalApiManager;
49     private final InterfacemgrProvider interfaceMgrProvider;
50
51     @Inject
52     public InterfaceConfigListener(final DataBroker dataBroker, final IdManagerService idManager,
53             final IMdsalApiManager mdsalApiManager, final InterfacemgrProvider interfaceMgrProvider,
54             final AlivenessMonitorService alivenessMonitorService) {
55         super(Interface.class, InterfaceConfigListener.class);
56         this.dataBroker = dataBroker;
57         this.idManager = idManager;
58         this.mdsalApiManager = mdsalApiManager;
59         this.interfaceMgrProvider = interfaceMgrProvider;
60         this.alivenessMonitorService = alivenessMonitorService;
61         this.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
62     }
63
64     @Override
65     protected InstanceIdentifier<Interface> getWildCardPath() {
66         return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
67     }
68
69     @Override
70     protected InterfaceConfigListener getDataTreeChangeListener() {
71         return InterfaceConfigListener.this;
72     }
73
74     private void updateInterfaceParentRefs(Interface iface) {
75         String ifName = iface.getName();
76         // try to acquire the parent interface name from Southbound
77         String parentRefName = interfaceMgrProvider.getParentRefNameForInterface(ifName);
78         if (parentRefName == null) {
79             LOG.debug("parent refs not specified for {}, failed acquiring it from southbound", ifName);
80             return;
81         }
82         LOG.debug("retrieved parent ref {} for interface {} from southbound, updating parentRef in datastore",
83                 parentRefName, ifName);
84         interfaceMgrProvider.updateInterfaceParentRef(ifName, parentRefName, false);
85         return;
86     }
87
88     @Override
89     protected void remove(InstanceIdentifier<Interface> key, Interface interfaceOld) {
90         IfmClusterUtils.runOnlyInLeaderNode(() -> {
91             LOG.debug("Received Interface Remove Event: {}, {}", key, interfaceOld);
92             String ifName = interfaceOld.getName();
93             ParentRefs parentRefs = interfaceOld.getAugmentation(ParentRefs.class);
94             if (parentRefs == null
95                     || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
96                 LOG.warn("parent refs not specified for {}", interfaceOld.getName());
97                 return;
98             }
99             boolean isTunnelInterface = InterfaceManagerCommonUtils.isTunnelInterface(interfaceOld);
100             DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
101             RendererConfigRemoveWorker configWorker = new RendererConfigRemoveWorker(key, interfaceOld,
102                     interfaceOld.getName(), parentRefs);
103             String synchronizationKey = isTunnelInterface ? parentRefs.getDatapathNodeIdentifier().toString()
104                     : parentRefs.getParentInterface();
105             coordinator.enqueueJob(synchronizationKey, configWorker, IfmConstants.JOB_MAX_RETRIES);
106         }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
107     }
108
109     @Override
110     protected void update(InstanceIdentifier<Interface> key, Interface interfaceOld, Interface interfaceNew) {
111         IfmClusterUtils.runOnlyInLeaderNode(() -> {
112             LOG.debug("Received Interface Update Event: {}, {}, {}", key, interfaceOld, interfaceNew);
113             ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
114             if (parentRefs == null || parentRefs.getParentInterface() == null) {
115                 // If parentRefs are missing, try to find a matching parent and
116                 // update - this will trigger another DCN
117                 updateInterfaceParentRefs(interfaceNew);
118             }
119
120             String ifNameNew = interfaceNew.getName();
121             if (parentRefs == null
122                     || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
123                 LOG.debug("parent refs not specified for {}, or parentRefs {} missing DPN/parentInterface",
124                         interfaceNew.getName(), parentRefs);
125                 return;
126             }
127             boolean isTunnelInterface = InterfaceManagerCommonUtils.isTunnelInterface(interfaceOld);
128             DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
129             RendererConfigUpdateWorker configWorker = new RendererConfigUpdateWorker(key, interfaceOld, interfaceNew,
130                     interfaceNew.getName());
131             String synchronizationKey = isTunnelInterface ? interfaceOld.getName() : parentRefs.getParentInterface();
132             coordinator.enqueueJob(synchronizationKey, configWorker, IfmConstants.JOB_MAX_RETRIES);
133
134         }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
135     }
136
137     @Override
138     protected void add(InstanceIdentifier<Interface> key, Interface interfaceNew) {
139         IfmClusterUtils.runOnlyInLeaderNode(() -> {
140             LOG.debug("Received Interface Add Event: {}, {}", key, interfaceNew);
141             ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
142             if (parentRefs == null || parentRefs.getParentInterface() == null) {
143                 // If parentRefs are missing, try to find a matching parent and
144                 // update - this will trigger another DCN
145                 updateInterfaceParentRefs(interfaceNew);
146             }
147
148             String ifName = interfaceNew.getName();
149             if (parentRefs == null
150                     || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
151                 LOG.warn("parent refs not specified for {}", interfaceNew.getName());
152                 return;
153             }
154             boolean isTunnelInterface = InterfaceManagerCommonUtils.isTunnelInterface(interfaceNew);
155             DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
156             RendererConfigAddWorker configWorker = new RendererConfigAddWorker(key, interfaceNew, parentRefs,
157                     interfaceNew.getName());
158             String synchronizationKey = isTunnelInterface ? interfaceNew.getName() : parentRefs.getParentInterface();
159             coordinator.enqueueJob(synchronizationKey, configWorker, IfmConstants.JOB_MAX_RETRIES);
160         }, IfmClusterUtils.INTERFACE_CONFIG_ENTITY);
161     }
162
163     private class RendererConfigAddWorker implements Callable<List<ListenableFuture<Void>>> {
164         InstanceIdentifier<Interface> key;
165         Interface interfaceNew;
166         String portName;
167         ParentRefs parentRefs;
168
169         RendererConfigAddWorker(InstanceIdentifier<Interface> key, Interface interfaceNew, ParentRefs parentRefs,
170                 String portName) {
171             this.key = key;
172             this.interfaceNew = interfaceNew;
173             this.portName = portName;
174             this.parentRefs = parentRefs;
175         }
176
177         @Override
178         public List<ListenableFuture<Void>> call() {
179             // If another renderer(for eg : CSS) needs to be supported, check
180             // can be performed here
181             // to call the respective helpers.
182             return OvsInterfaceConfigAddHelper.addConfiguration(dataBroker, parentRefs, interfaceNew, idManager,
183                     alivenessMonitorService, mdsalApiManager);
184         }
185
186         @Override
187         public String toString() {
188             return "RendererConfigAddWorker{" + "key=" + key + ", interfaceNew=" + interfaceNew + ", portName='"
189                     + portName + '\'' + '}';
190         }
191     }
192
193     private class RendererConfigUpdateWorker implements Callable {
194         InstanceIdentifier<Interface> key;
195         Interface interfaceOld;
196         Interface interfaceNew;
197         String portNameNew;
198
199         RendererConfigUpdateWorker(InstanceIdentifier<Interface> key, Interface interfaceOld,
200                 Interface interfaceNew, String portNameNew) {
201             this.key = key;
202             this.interfaceOld = interfaceOld;
203             this.interfaceNew = interfaceNew;
204             this.portNameNew = portNameNew;
205         }
206
207         @Override
208         public List<ListenableFuture<Void>> call() {
209             // If another renderer(for eg : CSS) needs to be supported, check
210             // can be performed here
211             // to call the respective helpers.
212             return OvsInterfaceConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager,
213                     mdsalApiManager, interfaceNew, interfaceOld);
214         }
215
216         @Override
217         public String toString() {
218             return "RendererConfigUpdateWorker{" + "key=" + key + ", interfaceOld=" + interfaceOld + ", interfaceNew="
219                     + interfaceNew + ", portNameNew='" + portNameNew + '\'' + '}';
220         }
221     }
222
223     private class RendererConfigRemoveWorker implements Callable {
224         InstanceIdentifier<Interface> key;
225         Interface interfaceOld;
226         String portName;
227         ParentRefs parentRefs;
228
229         RendererConfigRemoveWorker(InstanceIdentifier<Interface> key, Interface interfaceOld, String portName,
230                 ParentRefs parentRefs) {
231             this.key = key;
232             this.interfaceOld = interfaceOld;
233             this.portName = portName;
234             this.parentRefs = parentRefs;
235         }
236
237         @Override
238         public List<ListenableFuture<Void>> call() {
239             // If another renderer(for eg : CSS) needs to be supported, check
240             // can be performed here
241             // to call the respective helpers.
242             return OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, alivenessMonitorService, interfaceOld,
243                     idManager, mdsalApiManager, parentRefs);
244         }
245
246         @Override
247         public String toString() {
248             return "RendererConfigRemoveWorker{" + "key=" + key + ", interfaceOld=" + interfaceOld + ", portName='"
249                     + portName + '\'' + '}';
250         }
251     }
252 }