2 * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. 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.netvirt.vpnmanager;
10 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
21 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
22 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
31 import org.opendaylight.yangtools.concepts.ListenerRegistration;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import java.math.BigInteger;
37 import java.util.List;
38 import java.util.concurrent.Callable;
39 import java.util.concurrent.ExecutionException;
41 public class InterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
42 private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
43 private ListenerRegistration<DataChangeListener> listenerRegistration;
44 private final DataBroker dataBroker;
45 private final VpnInterfaceManager vpnInterfaceManager;
47 public InterfaceStateChangeListener(final DataBroker dataBroker, VpnInterfaceManager vpnInterfaceManager) {
48 super(Interface.class);
49 this.dataBroker = dataBroker;
50 this.vpnInterfaceManager = vpnInterfaceManager;
54 LOG.info("{} start", getClass().getSimpleName());
55 listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
56 getWildCardPath(), this, DataChangeScope.SUBTREE);
59 private InstanceIdentifier<Interface> getWildCardPath() {
60 return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
64 public void close() throws Exception {
65 if (listenerRegistration != null) {
66 listenerRegistration.close();
67 listenerRegistration = null;
69 LOG.info("{} close", getClass().getSimpleName());
73 protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
74 LOG.trace("Received interface {} add event", intrf);
76 final String interfaceName = intrf.getName();
77 LOG.info("Received interface add event for interface {} ", interfaceName);
78 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
79 configInterface = InterfaceUtils.getInterface(dataBroker, interfaceName);
80 if (configInterface != null) {
81 if (!configInterface.getType().equals(Tunnel.class)) {
82 // We service only VM interfaces and Router interfaces here.
83 // We donot service Tunnel Interfaces here.
84 // Tunnel events are directly serviced
85 // by TunnelInterfacesStateListener present as part of VpnInterfaceManager
86 LOG.debug("Config Interface Name {}", configInterface.getName());
87 final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
88 if (vpnInterface != null) {
89 LOG.debug("VPN Interface Name {}", vpnInterface);
90 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
91 final int ifIndex = intrf.getIfIndex();
92 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
93 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
94 new Callable<List<ListenableFuture<Void>>>() {
96 public List<ListenableFuture<Void>> call() throws Exception {
97 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
98 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
99 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
100 vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false,
101 writeConfigTxn, writeOperTxn, writeInvTxn);
102 String routerName = VpnUtil.getNeutronRouterFromInterface(dataBroker, interfaceName);
103 if (routerName != null) {
104 LOG.debug("Router Name {} ", routerName);
105 handleRouterInterfacesUpEvent(routerName, interfaceName, writeOperTxn);
107 LOG.info("Unable to process add for interface {} for NAT service", interfaceName);
109 CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
112 } catch (InterruptedException | ExecutionException e) {
113 LOG.error("Error adding Oper data for interface {} to vpn {} on dpn {}", interfaceName,
114 vpnInterface.getVpnInstanceName(), dpnId);
115 throw new RuntimeException(e.getMessage());
117 futures = writeConfigTxn.submit();
120 } catch (InterruptedException | ExecutionException e) {
121 LOG.error("Error adding Config data for interface {} to vpn {} on dpn {}", interfaceName,
122 vpnInterface.getVpnInstanceName(), dpnId);
123 throw new RuntimeException(e.getMessage());
125 futures = writeInvTxn.submit();
128 } catch (InterruptedException | ExecutionException e) {
129 LOG.error("Error adding inventory/flow data for interface {} to vpn {} on dpn {}", interfaceName,
130 vpnInterface.getVpnInstanceName(), dpnId);
131 throw new RuntimeException(e.getMessage());
133 LOG.warn("InterfaceStateChangeListner returning null while adding the " +
134 "interface {}", interfaceName);
141 LOG.error("Unable to process add for interface {} ," +
142 "since Interface ConfigDS entry absent for the same", interfaceName);
144 } catch (Exception e) {
145 LOG.error("Exception caught in Interface Operational State Up event", e);
150 protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
151 LOG.trace("Received interface {} down event", intrf);
153 final String interfaceName = intrf.getName();
154 LOG.info("Received port DOWN event for interface {} ", interfaceName);
155 if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
156 //withdraw all prefixes in all vpns for this dpn from bgp
157 // FIXME: Blocked until tunnel event[vxlan/gre] support is available
158 // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
160 BigInteger dpId = BigInteger.ZERO;
161 InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
162 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
163 if (!optVpnInterface.isPresent()) {
164 LOG.debug("Interface {} is not a vpninterface, ignoring.", intrf.getName());
167 final VpnInterface vpnInterface = optVpnInterface.get();
169 dpId = InterfaceUtils.getDpIdFromInterface(intrf);
170 } catch (Exception e){
171 LOG.warn("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", intrf.getName(), e);
172 dpId = vpnInterface.getDpnId();
174 final BigInteger dpnId = dpId;
175 final int ifIndex = intrf.getIfIndex();
176 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
177 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
178 new Callable<List<ListenableFuture<Void>>>() {
180 public List<ListenableFuture<Void>> call() throws Exception {
181 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
182 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
183 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
184 vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, false, false,
185 writeConfigTxn, writeOperTxn, writeInvTxn);
186 RouterInterface routerInterface = VpnUtil.getConfiguredRouterInterface(dataBroker, interfaceName);
187 if (routerInterface != null) {
188 handleRouterInterfacesDownEvent(routerInterface.getRouterName(), interfaceName, dpnId, writeOperTxn);
190 CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
193 } catch (InterruptedException | ExecutionException e) {
194 LOG.error("Error removing Oper data for interface {} from vpn {} on dpn {}", interfaceName,
195 vpnInterface.getVpnInstanceName(), dpnId);
196 throw new RuntimeException(e.getMessage());
198 futures = writeConfigTxn.submit();
201 } catch (InterruptedException | ExecutionException e) {
202 LOG.error("Error removing Config data for interface {} from vpn {} on dpn {}", interfaceName,
203 vpnInterface.getVpnInstanceName(), dpnId);
204 throw new RuntimeException(e.getMessage());
206 futures = writeInvTxn.submit();
209 } catch (InterruptedException | ExecutionException e) {
210 LOG.error("Error removing Inventory/Flow data for interface {} from vpn {} on dpn {}", interfaceName,
211 vpnInterface.getVpnInstanceName(), dpnId);
212 throw new RuntimeException(e.getMessage());
218 } catch (Exception e) {
219 LOG.error("Exception observed in handling deletion of VPN Interface {}. ", intrf.getName(), e);
224 protected void update(InstanceIdentifier<Interface> identifier,
225 Interface original, Interface update) {
226 LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
227 final String interfaceName = update.getName();
228 if (original.getOperStatus().equals(Interface.OperStatus.Unknown) ||
229 update.getOperStatus().equals(Interface.OperStatus.Unknown)){
230 LOG.debug("Interface {} state change is from/to UNKNOWN. Ignoring the update event.", interfaceName);
233 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
234 final int ifIndex = update.getIfIndex();
235 if (update != null) {
236 if (!update.getType().equals(Tunnel.class)) {
237 final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
238 if (vpnInterface != null) {
239 if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
240 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
241 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
242 new Callable<List<ListenableFuture<Void>>>() {
244 public List<ListenableFuture<Void>> call() throws Exception {
245 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
246 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
247 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
248 vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex,
249 true, writeConfigTxn, writeOperTxn, writeInvTxn);
250 CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
253 } catch (InterruptedException | ExecutionException e) {
254 LOG.error("Error updating oper data for interface {} in vpn {} on dpn {}", interfaceName,
255 vpnInterface.getVpnInstanceName(), dpnId);
256 throw new RuntimeException(e.getMessage());
258 futures = writeConfigTxn.submit();
261 } catch (InterruptedException | ExecutionException e) {
262 LOG.error("Error updating config data for interface {} in vpn {} on dpn {}", interfaceName,
263 vpnInterface.getVpnInstanceName(), dpnId);
264 throw new RuntimeException(e.getMessage());
266 futures = writeInvTxn.submit();
269 } catch (InterruptedException | ExecutionException e) {
270 LOG.error("Error adding inventory/flow data for interface {} to vpn {} on dpn {}", interfaceName,
271 vpnInterface.getVpnInstanceName(), dpnId);
272 throw new RuntimeException(e.getMessage());
277 } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
278 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
279 dataStoreCoordinator.enqueueJob(interfaceName,
280 new Callable<List<ListenableFuture<Void>>>() {
282 public List<ListenableFuture<Void>> call() throws Exception {
283 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
284 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
285 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
286 vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, true, false,
287 writeConfigTxn, writeOperTxn, writeInvTxn);
288 CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
291 } catch (InterruptedException | ExecutionException e) {
292 LOG.error("Error updating oper data for interface {} from vpn {} on dpn {}", interfaceName,
293 vpnInterface.getVpnInstanceName(), dpnId);
294 throw new RuntimeException(e.getMessage());
296 futures = writeConfigTxn.submit();
299 } catch (InterruptedException | ExecutionException e) {
300 LOG.error("Error updating config data for interface {} from vpn {} on dpn {}", interfaceName,
301 vpnInterface.getVpnInstanceName(), dpnId);
302 throw new RuntimeException(e.getMessage());
304 futures = writeInvTxn.submit();
307 } catch (InterruptedException | ExecutionException e) {
308 LOG.error("Error updating inventory/flow for interface {} from vpn {} on dpn {}", interfaceName,
309 vpnInterface.getVpnInstanceName(), dpnId);
310 throw new RuntimeException(e.getMessage());
321 void handleRouterInterfacesUpEvent(String routerName, String interfaceName, WriteTransaction writeOperTxn) {
322 LOG.debug("Handling UP event for router interface {} in Router {}", interfaceName, routerName);
323 vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName, writeOperTxn);
326 void handleRouterInterfacesDownEvent(String routerName, String interfaceName, BigInteger dpnId,
327 WriteTransaction writeOperTxn) {
328 LOG.debug("Handling DOWN event for router interface {} in Router {}", interfaceName, routerName);
329 vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName, dpnId, writeOperTxn);